Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > pl.comp.lang.javascript > #3482 > unrolled thread

Promise i oczekiwanie na wynik

Started byRoman Tyczka <noemail@because.no>
First post2018-08-07 16:35 +0200
Last post2018-08-10 22:31 +0200
Articles 8 — 3 participants

Back to article view | Back to pl.comp.lang.javascript


Contents

  Promise i oczekiwanie na wynik Roman Tyczka <noemail@because.no> - 2018-08-07 16:35 +0200
    Re: Promise i oczekiwanie na wynik Borys Pogoreło <borys@pl.edu.leszno> - 2018-08-08 22:29 +0200
      Re: Promise i oczekiwanie na wynik Roman Tyczka <noemail@because.no> - 2018-08-08 23:34 +0200
        Re: Promise i oczekiwanie na wynik Borys Pogoreło <borys@pl.edu.leszno> - 2018-08-10 11:53 +0200
          Re: Promise i oczekiwanie na wynik Roman Tyczka <noemail@because.no> - 2018-08-10 12:49 +0200
          Re: Promise i oczekiwanie na wynik Cezary Tomczyk <cezary.tomczyk@gmail.com> - 2018-08-10 17:22 +0300
            Re: Promise i oczekiwanie na wynik Roman Tyczka <noemail@because.no> - 2018-08-10 18:19 +0200
              Re: Promise i oczekiwanie na wynik Borys Pogoreło <borys@pl.edu.leszno> - 2018-08-10 22:31 +0200

#3482 — Promise i oczekiwanie na wynik

FromRoman Tyczka <noemail@because.no>
Date2018-08-07 16:35 +0200
SubjectPromise i oczekiwanie na wynik
Message-ID<1jv3988qj6pyf.dlg@tyczka.com>
Witam,

Moje boje z JS utknęły na tym, że liczenie haszy w bibliotece standardowej
jest asynchroniczne i całość rozbija się o obiekt typu Promise zwracany z
metody digest().
Czytam o tym nieszczęsnym Promise i nie ogarniam.
Chciałbym poczekać aż w tle zostanie policzony czas, więc na końcu funkcji
haszującej dopisuję:


 Promise.race([hash_promise]).then(function (value) {
			haszyk = value;
		});
 return haszyk;

spodziewając się, że race() będzie czekać, tymczasem race() przechodzi bez
zatrzymania, mimo, że hash_promise nadal jest pending i do return trafia
pusty string haszyk, bo go nikt nie wypełnił.

Jak zmusić JS, żeby czekał aż asynchroniczne zadanie będzie wykonane?

-- 
pozdrawiam
Roman Tyczka

[toc] | [next] | [standalone]


#3484

FromBorys Pogoreło <borys@pl.edu.leszno>
Date2018-08-08 22:29 +0200
Message-ID<nu2wq6mg704y$.wuh3wxwx318r$.dlg@40tude.net>
In reply to#3482
Dnia Tue, 7 Aug 2018 16:35:54 +0200, Roman Tyczka napisał(a):

> spodziewając się, że race() będzie czekać, tymczasem race() przechodzi bez
> zatrzymania, mimo, że hash_promise nadal jest pending i do return trafia
> pusty string haszyk, bo go nikt nie wypełnił.

Nie wkleiłeś całego kodu, ale czy przypadkiem nie zwracasz zmiennej
"haszyk" od razu? Ona zostanie zmieniona dopiero gdy Promise się rozwiąże.

I generalnie Promise.race() nie do tego służy. To stosunkowo rzadko
potrzebne narzędzie, które czeka na wynik jednej z wielu promises. Niby
można by tego użyć w zaproponowany przez Ciebie sposób, ale jest to
kompletnie zbędne. Wystarczy się od razu odwołać do obiektu.

> Jak zmusić JS, żeby czekał aż asynchroniczne zadanie będzie wykonane?

Nie zmusisz. Musisz myśleć asynchronicznie - kod operujący na wyniku
funkcji haszującej musi poczekać na wynik Promise:

https://jsfiddle.net/fzLbqmng/

-- 
Borys Pogoreło
borys(#)leszno,edu,pl

[toc] | [prev] | [next] | [standalone]


#3486

FromRoman Tyczka <noemail@because.no>
Date2018-08-08 23:34 +0200
Message-ID<1x6oxswxeel0t$.dlg@tyczka.com>
In reply to#3484
On Wed, 8 Aug 2018 22:29:26 +0200, Borys Pogoreło wrote:

> Dnia Tue, 7 Aug 2018 16:35:54 +0200, Roman Tyczka napisał(a):
> 
>> spodziewając się, że race() będzie czekać, tymczasem race() przechodzi bez
>> zatrzymania, mimo, że hash_promise nadal jest pending i do return trafia
>> pusty string haszyk, bo go nikt nie wypełnił.
> 
> Nie wkleiłeś całego kodu, ale czy przypadkiem nie zwracasz zmiennej
> "haszyk" od razu? Ona zostanie zmieniona dopiero gdy Promise się rozwiąże.
> 
> I generalnie Promise.race() nie do tego służy. To stosunkowo rzadko
> potrzebne narzędzie, które czeka na wynik jednej z wielu promises. Niby
> można by tego użyć w zaproponowany przez Ciebie sposób, ale jest to
> kompletnie zbędne. Wystarczy się od razu odwołać do obiektu.
> 
>> Jak zmusić JS, żeby czekał aż asynchroniczne zadanie będzie wykonane?
> 
> Nie zmusisz. Musisz myśleć asynchronicznie - kod operujący na wyniku
> funkcji haszującej musi poczekać na wynik Promise:
> 
> https://jsfiddle.net/fzLbqmng/

Powiedzmy, że rozumiem jako tako jak to działa, jest to dość sprytne.
Tylko, że teraz jest problem. Mam kod, który wywołuję pod buttonem, to
klasyczny kod sekwencyjny. Linia po linii zbiera dane, łączy stringi, liczy
hasze, coś tam jeszcze robi i na końcu wrzuca wynik do jakiegoś
pola/zmiennej. I jeśli teraz jedna potrzebna funkcja czyli hasz narzuca mi
styl asynchroniczny to zmusza do przeorania całego kodu na ten model i
wołania wszystkiego w kolejnych promisach i then'ach. Pewnie, że to fajne,
elastyczne i generalnie lepsze, ale są sytuacje gdy nie chcę przerabiać
kodu do tej wymuszonej asynchroniczności, co wtedy? 

Przykładowo mam stary kod:

 value = valueX + valuY + SHA512(valueZ);
 value = cryptoAES(value);

Prosta rzecz. A teraz muszę ten cały kod zawijać w, skądinnąd użyteczne,
ale wygibasy, promisów.

Czy mogę jakoś wymusić synchroniczność? Próbowałem z tym async/await ale to
nie zadziałało. Może coś źle robiłem, a może to musi być nowsza
przeglądarka.


ps. dlaczego w ogóle ten moduł crypto wsadzili w Promise? Z powodu
złożoności obliczeniowej i realnie długiego czasu wykonania?

-- 
pozdrawiam
Roman Tyczka

[toc] | [prev] | [next] | [standalone]


#3488

FromBorys Pogoreło <borys@pl.edu.leszno>
Date2018-08-10 11:53 +0200
Message-ID<19s5kvtfto3zr.bj8wdjlcy4l2.dlg@40tude.net>
In reply to#3486
Dnia Wed, 8 Aug 2018 23:34:09 +0200, Roman Tyczka napisał(a):

> I jeśli teraz jedna potrzebna funkcja czyli hasz narzuca mi
> styl asynchroniczny to zmusza do przeorania całego kodu na ten model i
> wołania wszystkiego w kolejnych promisach i then'ach. Pewnie, że to fajne,
> elastyczne i generalnie lepsze, ale są sytuacje gdy nie chcę przerabiać
> kodu do tej wymuszonej asynchroniczności, co wtedy? 

Wtedy masz problem ;)

Niestety kod asynchroniczny wymaga innej budowy i uwzględnienia tego, że
trzeba czekać na wynik. Nawet tylko jeden cykl CPU, ale trzeba.

> Czy mogę jakoś wymusić synchroniczność? Próbowałem z tym async/await ale to
> nie zadziałało. Może coś źle robiłem, a może to musi być nowsza
> przeglądarka.

To i to. W drugim wątku wrzuciłem przykład.

> ps. dlaczego w ogóle ten moduł crypto wsadzili w Promise? Z powodu
> złożoności obliczeniowej i realnie długiego czasu wykonania?

Tak. Wszelkie operacje synchroniczne blokują event loop.

-- 
Borys Pogoreło
borys(#)leszno,edu,pl

[toc] | [prev] | [next] | [standalone]


#3492

FromRoman Tyczka <noemail@because.no>
Date2018-08-10 12:49 +0200
Message-ID<f1k2ujtqa5x8$.dlg@tyczka.com>
In reply to#3488
On Fri, 10 Aug 2018 11:53:03 +0200, Borys Pogoreło wrote:

>> I jeśli teraz jedna potrzebna funkcja czyli hasz narzuca mi
>> styl asynchroniczny to zmusza do przeorania całego kodu na ten model i
>> wołania wszystkiego w kolejnych promisach i then'ach. Pewnie, że to fajne,
>> elastyczne i generalnie lepsze, ale są sytuacje gdy nie chcę przerabiać
>> kodu do tej wymuszonej asynchroniczności, co wtedy? 
> 
> Wtedy masz problem ;)
> 
> Niestety kod asynchroniczny wymaga innej budowy i uwzględnienia tego, że
> trzeba czekać na wynik. Nawet tylko jeden cykl CPU, ale trzeba.

[...]

>> ps. dlaczego w ogóle ten moduł crypto wsadzili w Promise? Z powodu
>> złożoności obliczeniowej i realnie długiego czasu wykonania?
> 
> Tak. Wszelkie operacje synchroniczne blokują event loop.

Powiedz mi jak to w ogóle działa pod spodem, skoro JS jest niby
jednowątkowy? Jak przerwania w epoce DOSa na PC AT?

-- 
pozdrawiam
Roman Tyczka

[toc] | [prev] | [next] | [standalone]


#3493

FromCezary Tomczyk <cezary.tomczyk@gmail.com>
Date2018-08-10 17:22 +0300
Message-ID<pkk72b$2gvk$1@csiph.com>
In reply to#3488
On 10/08/2018 12:53, Borys Pogoreło wrote:
> Dnia Wed, 8 Aug 2018 23:34:09 +0200, Roman Tyczka napisał(a):
[...]
>> ps. dlaczego w ogóle ten moduł crypto wsadzili w Promise? Z powodu
>> złożoności obliczeniowej i realnie długiego czasu wykonania?
> 
> Tak. Wszelkie operacje synchroniczne blokują event loop.

Garść o tym: 
https://medium.com/@siddharthac6/javascript-execution-of-synchronous-and-asynchronous-codes-40f3a199e687

-- 
Cezary Tomczyk
http://www.ctomczyk.pl/

[toc] | [prev] | [next] | [standalone]


#3494

FromRoman Tyczka <noemail@because.no>
Date2018-08-10 18:19 +0200
Message-ID<3gdptg2lfrnd.dlg@tyczka.com>
In reply to#3493
On Fri, 10 Aug 2018 17:22:02 +0300, Cezary Tomczyk wrote:

> On 10/08/2018 12:53, Borys Pogoreło wrote:
>> Dnia Wed, 8 Aug 2018 23:34:09 +0200, Roman Tyczka napisał(a):
> [...]
>>> ps. dlaczego w ogóle ten moduł crypto wsadzili w Promise? Z powodu
>>> złożoności obliczeniowej i realnie długiego czasu wykonania?
>> 
>> Tak. Wszelkie operacje synchroniczne blokują event loop.
> 
> Garść o tym: 
> https://medium.com/@siddharthac6/javascript-execution-of-synchronous-and-asynchronous-codes-40f3a199e687

To nie wyjaśnia wszystkiego, bo użyty został fatalny przykład z tym
setTimeout(). Czekanie 2 sekundy nic nie kosztuje. I jest łatwe do
implementacji tak jak to opisano.
Ale co z sytuacją, gdy funkcja asynchroniczna robi coś "grubego" w tle, jak
choćby to liczenie hasza? 
Czy wtedy:
a) jest oczekiwanie na pustego call stacka i wrzucenie całego "grubego"
zadania do wykonania (tak wynika z artykułu)?
b) czy może to poboczne zadanie jest dzielone na fragmenciki i wywoływane
po kawałku w wolnych chwilach (tak jak w aplikacjach z prawdziwą
wielowątkowościa)?

Druga opcja ma większy sens, ale jest dużo trudniejsza w implementacji.
Zatem nadal nie wiem czy wiem co się tam tak naprawdę dzieje :-)

Zwłaszcza, że autor arta sam pisze na końcu:

"I don’t know how accurately I am able to demonstrate this topic but there
are a lot in between that could have been elaborated or explained better,
but am in a rush and it’s already too long already. Hope it helps someone."

ps. W Delphi (jeśli mowa o programowaniu bez wątków) też istnieje coś
takiego jak timer i też można mu zapodać zrobienie czegoś za określony czas
i działa to tak jak opisano w tym artykule, czyli pętla komunikatów dostaje
komunikat WM_TIMER i adres procedury obsługi, którą wywołuje jeśli nie jest
akurat niczym zajęta. To dość uboga "asynchroniczność", ale czasami
wystarcza. Gdyby jednak procedura spod timera była długotrwała to pętla
komunikatów zostanie zablokowana i aplikacja przestanie odpowiadać (często
to widać w źle napisanych aplikacjach, gdy GUI przestaje się rysować i nie
działają kontrolki).

-- 
pozdrawiam
Roman Tyczka

[toc] | [prev] | [next] | [standalone]


#3496

FromBorys Pogoreło <borys@pl.edu.leszno>
Date2018-08-10 22:31 +0200
Message-ID<1isg2tvyhs2z2$.11w8obwnohoid$.dlg@40tude.net>
In reply to#3494
Dnia Fri, 10 Aug 2018 18:19:58 +0200, Roman Tyczka napisał(a):

> Ale co z sytuacją, gdy funkcja asynchroniczna robi coś "grubego" w tle, jak
> choćby to liczenie hasza? 
> Czy wtedy:
> a) jest oczekiwanie na pustego call stacka i wrzucenie całego "grubego"
> zadania do wykonania (tak wynika z artykułu)?

Całe zadanie. Jednowątkowość do bólu (pominąwszy webworkery). Dlatego warto
jak najbardziej kroić skomplikowany kod.

> wystarcza. Gdyby jednak procedura spod timera była długotrwała to pętla
> komunikatów zostanie zablokowana i aplikacja przestanie odpowiadać (często
> to widać w źle napisanych aplikacjach, gdy GUI przestaje się rysować i nie
> działają kontrolki).

Javascriptem też zablokujesz UI, jeśli odpalisz coś "ciężkiego".

-- 
Borys Pogoreło
borys(#)leszno,edu,pl

[toc] | [prev] | [standalone]


Back to top | Article view | pl.comp.lang.javascript


csiph-web