Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Asynchroniczna pętla, Rozważania nad API
Comandeer
post
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ą:
  • Czy oparcie bebechów tego czegoś na Promise.all/Promise brzmi sensownie?
  • Czy lepiej udostępnić userowi dostęp do obiecanki wewnątrz X.each i nie mieć kontroli nad tym, co zwróci całość, czy dać mu jedynie dostęp do done i w pełni kontrolować to, co zostanie zwrócone?
  • X.each czy X.forEachAsync? (IMG:style_emoticons/default/wink.gif) Chociaż pewnie każdy, kto pracował kiedyś z jQuery i tak wybierze 1. wersję
Go to the top of the page
+Quote Post
salfunglandyare
post
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)
Go to the top of the page
+Quote Post
Comandeer
post
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ąć?
Go to the top of the page
+Quote Post
salfunglandyare
post
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(){
});
Go to the top of the page
+Quote Post
Crozin
post
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
Go to the top of the page
+Quote Post
Comandeer
post
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)
Go to the top of the page
+Quote Post
salfunglandyare
post
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
Go to the top of the page
+Quote Post
Comandeer
post
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
Go to the top of the page
+Quote Post
salfunglandyare
post
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)
Go to the top of the page
+Quote Post
Comandeer
post
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
Go to the top of the page
+Quote Post
salfunglandyare
post
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)
Go to the top of the page
+Quote Post
Comandeer
post
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
Go to the top of the page
+Quote Post
by_ikar
post
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
Go to the top of the page
+Quote Post
Comandeer
post
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)
Go to the top of the page
+Quote Post
by_ikar
post
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)
Go to the top of the page
+Quote Post
Comandeer
post
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
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 21.12.2025 - 19:43