![]() ![]() |
Post
#1
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Pytanie natury czysto teoretycznej. Załóżmy, że tworzę sobie API dla pewnego projektu X i musi być ono de facto w pełni asynchroniczne. Oczywistym wyborem są tutaj obiecanki - wszak nikt nie lubi się babrać w callbackach.
Wszystko jest cacy, ALE (IMG:style_emoticons/default/wink.gif) Potrzebna jest mi asynchroniczna wersja pętli [].forEach - metoda X.each (żeby się nikt nie rąbnął z natywnym [].forEach; chyba żeby iść w coś typu X.forEachAsync?). Na każdym elemencie mogą być wykonywane operacje asynchroniczne i pętla powinna "czekać". Na chłopski rozum implementacja powinna się opierać na Promise.all i każdy przepuszczany przez X.each element powinien być obiecanką. Tak na szybko "backend" czegoś takiego mógłby wyglądać np. tak (oczywiście pewnie będzie wyglądać ciut bardziej złożenie (IMG:style_emoticons/default/wink.gif) ): Kod var promises = []; pool.forEach(function(item) { var promise = toPromise(item); callback(promise); promises.push(promise); }); return Promises.all(promises); Zatem wywołanie X.each wyglądałoby następująco: Kod X.each(function(promise) { }) .then(function(returnValues) { //po pętelce }); User dostawałby po prostu dostęp do obiecanki - proste i przyjemne. Pojawia się jednak pewien problem: zaburza to koncepcję chainingu - przy takim wywołaniu nie dostaniemy pojedynczej wartości (a zatem mitycznego this) tylko tablicę dowolnych wartości (user może zwrócić wszystko w obiecance). W zależności od naszego widzimisię może to być dobrze lub źle (ale raczej źle). Stąd myślę czy nie ograniczyć możliwości usera wprowadzając pewien rodzaj nakładki, analogiczny do tego, jaką udostępniają np. taski asynchroniczne w Gruncie - user miałby dostęp tylko do funkcji done (z tym, że wówczas bebechy operowałyby raczej na pojedynczynm Promise a nie ich tablicy): Kod X.each(function(done) { done(); //wszystko cacy done(jakakolwiekWartosc); //coś się zepsuło }) .then(function(X) { //itd }); Tym sposobem w X.each().then na pewno uzyskamy z powrotem X, co np. w dalszej kolejności uprzyjemni obcowanie z biblioteką przy wykorzystywaniu generatorów. Pytania brzmią:
|
|
|
|
Post
#2
|
|
|
Grupa: Zarejestrowani Postów: 150 Pomógł: 31 Dołączył: 10.01.2007 Skąd: Bydgoszcz/Inowrocław Ostrzeżenie: (0%)
|
To zależy jak wierzysz w obiecanki (IMG:style_emoticons/default/smile.gif) obiecanki-cacanki, a w życiu... no właśnie. Ja bym dał raczej dostęp na done, choć to nie zupełnie nie wygląda tak, jak to pokazałeś (IMG:style_emoticons/default/smile.gif)
|
|
|
|
Post
#3
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Cytat Ja bym dał raczej dostęp na done, choć to nie zupełnie nie wygląda tak, jak to pokazałeś Nie bardzo rozumiem - możesz rozwinąć? |
|
|
|
Post
#4
|
|
|
Grupa: Zarejestrowani Postów: 150 Pomógł: 31 Dołączył: 10.01.2007 Skąd: Bydgoszcz/Inowrocław Ostrzeżenie: (0%)
|
.....done(function(){
}); |
|
|
|
Post
#5
|
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%)
|
Czyżbyś szukał czegoś takiego? http://stackoverflow.com/a/23069551/252591
|
|
|
|
Post
#6
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
@salfunglandyare nie do końca o to chodzi. To, co pokazałeś, to pattern zaczerpnięty z jQuery, gdzie faktycznie obiekt Deferred posiada taką metodę. Mnie chodzi raczej o done jak tutaj: http://gruntjs.com/creating-tasks#custom-tasks (3 kod)
@Crozin ktoś tam coś zdrowo przekombinował… to, co pokazałeś, bardziej bym nazwał LazyPromise niż asynchroniczną pętlą (i w sumie podsunąłeś mi myśl jak taki LazyPromise zrobić (IMG:style_emoticons/default/wink.gif) ). W podanym przez Ciebie linku aż się prosi wykorzystać Promise.all - z tym, że nie wiem czy z jQuery by to zadziałało (bo oczywiście nie trzymają się standardu A+ tylko starszego…). Niemniej gościu na tyle przekombinował, że i tak mi się to przyda (IMG:style_emoticons/default/biggrin.gif) |
|
|
|
Post
#7
|
|
|
Grupa: Zarejestrowani Postów: 150 Pomógł: 31 Dołączył: 10.01.2007 Skąd: Bydgoszcz/Inowrocław Ostrzeżenie: (0%)
|
Rozumiem, ale done nie pojawi Ci się ot tak przy each czy foreach, jeśli robisz then w taki sposob, powinieneś również odpowiednio użyć done, inaczej wprowadzasz w blad. Niestety asynchroniczna synchroniczność na bazie promises w js to w dalszym ciagu callbacki na eventach w ladniejszym opakowaniu.
//edit: dodano "na eventach" powyzej //edit2: poza tym wykonanie done w przypadku, który napisałeś to zupełnie co innego i jest troche oszukane (IMG:style_emoticons/default/tongue.gif) done w tym przypadku jest f-cja wewnetrzna wywolywana coprawda asynchronicznie, ale nie majaca wplywu na kontekst Ten post edytował salfunglandyare 15.05.2015, 00:30:48 |
|
|
|
Post
#8
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Dlatego wgl o tym done pomyślałem, żeby móc uruchamiać całość wewnątrz generatora, co by uprościło składnię do de facto minimum. Wówczas mielibyśmy prawie synchroniczny kod.
Owszem, done nie pojawi mi się od tak. Widzę to jako prostą funkcję, która resolvuje promise jeśli nic jej nie przekazaliśmy i rejectuje jeśli dostanie parametr. I funkcja ta byłaby przekazywana do pętli zamiast całej obiecanki. Co do wprowadzania w błąd - done nie jest częścią standardu obiecanek, więc nie bardzo wiem gdzie tu wprowadzanie w błąd? https://promisesaplus.com tą metodę wprowadza raptem kilka bibliotek + niekompatybilna ze standardem składnia jQuery. W natywnej implementacji obiecanek w ES6 metoda ta nie występuje, bo jedyne co robi to dubluje then |
|
|
|
Post
#9
|
|
|
Grupa: Zarejestrowani Postów: 150 Pomógł: 31 Dołączył: 10.01.2007 Skąd: Bydgoszcz/Inowrocław Ostrzeżenie: (0%)
|
masz rację, ale to dlatego, że nie ma pomysłu do implementacji, co ona miałaby robić. Promises w założeniu są świetne, w wykonaniu muszą jeszcze poczekać. Done ma być ostatecznym krokiem, then powinien być jednostkowy. piszac .then().then().then().done() okreslsamy, ile ma być kroków do uzyskania. W tej chwili nie ma za dużej możliwości, żeby sprawdzić done, gdyż to jest kolejny element then, dlatego done = then... Osobiście wole polegac na $.ajax{ success: function(){moje_done() || moje_then()}} ale nie dlatego, że nie lubie obiecanek... po prostu w nie nie wierze (IMG:style_emoticons/default/tongue.gif)
|
|
|
|
Post
#10
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Z tym, że mówienie o obiecankach w kontekście jQuery to lekka herezja - tam to jest * a nie porządny promise (IMG:style_emoticons/default/wink.gif) akurat ja uważam odwrotnie niż Ty i widziałbym po prostu then. No i to, co mówisz, to pasuje bardziej do finally, które kilka bibliotek zaimplementowało u siebie.
Poza tym done nie do końca zachowuje się jak then, bo faktycznie przerywa łańcuch wywołań. Niemniej nie wnosi de facto nic ponad to Jeśli nie wierzysz w obiecanki, to polecam spojrzeć co na ich kanwie przygotowano w ES7, czyli async functions (IMG:style_emoticons/default/wink.gif) Ten post edytował Comandeer 15.05.2015, 00:56:07 |
|
|
|
Post
#11
|
|
|
Grupa: Zarejestrowani Postów: 150 Pomógł: 31 Dołączył: 10.01.2007 Skąd: Bydgoszcz/Inowrocław Ostrzeżenie: (0%)
|
widzisz, ja widzialbym w obiecankach then = done = finally, ale nie jest tak prosto i nie bedzie. Ja sie nie upieram zupelnie na jquery ale widze, jak to dziala na innych bibliotekach i to sa po prostu eventy na zdarzeniach wywolujace callbacki jesli sa. Nie czarujmy sie, nie zrobisz z malucha mercedesa, chocby charczal i sapal jak rasowy merc. Dostajemy cos pomiedzy, co jest w sumie tak naprawde zupelnie niepotrzebne, bo bedzie wymienione na inne rozwiazania szybsze, bardziej odpowiadajace na takie problemy (proponuje porownanie promises, chocby tych z jquery z websockets)
|
|
|
|
Post
#12
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Nie bardzo rozumiem co mają promises do modelu zdarzeniowego? Przecież one są całkowicie niezależne od siebie
|
|
|
|
Post
#13
|
|
|
Grupa: Zarejestrowani Postów: 1 798 Pomógł: 307 Dołączył: 13.05.2009 Skąd: Gubin/Wrocław Ostrzeżenie: (0%)
|
Osobiście do promises/deferred po stronie serwera używam q: https://github.com/kriskowal/q#combination który posiada metodę all gdzie można wrzucić tablicę obietnic i każda z nich jest wykonywana asynchronicznie. Jakiś czas temu przerabiałem wiele libów do obietnic, i w sumie q, najbardziej przypadło mi do gustu, ze względu na możliwości i prostotę zapisu.
https://github.com/kriskowal/q/wiki/API-Ref...r-array-methods lepsza dokumentacja tej metody: https://github.com/kriskowal/q/wiki/API-Ref...r-array-methods Ten post edytował by_ikar 15.05.2015, 07:34:23 |
|
|
|
Post
#14
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Q znam, ale raczej zostanę przy natywnej implementacji promises - w teorii powinno być szybciej (ale ręki se nie dam uciąć czy faktycznie jest, więc pewnie zostaną benchmarki)
|
|
|
|
Post
#15
|
|
|
Grupa: Zarejestrowani Postów: 1 798 Pomógł: 307 Dołączył: 13.05.2009 Skąd: Gubin/Wrocław Ostrzeżenie: (0%)
|
Cóż, jeżeli chodzi o wydajność, to tutaj są jakieś świeże testy: https://github.com/petkaantonov/bluebird/tr...aster/benchmark i według nich, natywne implementacje nie koniecznie są takie szybkie jakby się mogło wydawać. Z tego wszystkiego wychodzi, że when.js jest na prawdę kawałkiem dobrego kodu, bo to już chyba któryś z rzędu benchmark w którym when.js stoi na wysokim poziomie. Czas zrewidować chyba swoją wiedzę i przyzwyczajenia o Q (IMG:style_emoticons/default/wink.gif)
|
|
|
|
Post
#16
|
|
|
Grupa: Zarejestrowani Postów: 1 268 Pomógł: 254 Dołączył: 11.06.2009 Skąd: Świętochłowice Ostrzeżenie: (0%)
|
Cóz, bluebird od dawna jest jedną z najszybszych implementacji. Boli jedynie fakt, że implementacja natywna (a więc w c) jest 4 razy wolniejsza… na razie jednak zostanę przy natywnej, może nie dla samej wydajności, ale żeby nie mieć niepotrzebnego narzutu w kodzie. W razie potrzeby wplecenie w to bluebirda czy innej biblioteki będzie dziecinnie proste
|
|
|
|
![]() ![]() |
|
Aktualny czas: 21.12.2025 - 19:43 |