Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Bonjou tout moun. An kontak Omelnitsky Sergey. Pa tèlman lontan de sa, mwen te òganize yon kouran sou pwogram reyaktif, kote mwen te pale sou asynchrony nan JavaScript. Jodi a mwen ta renmen rezime materyèl sa a.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Men, anvan nou kòmanse materyèl prensipal la, nou bezwen fè yon entwodiksyon. Se konsa, ann kòmanse ak definisyon: ki sa ki pile ak keu?

Pile se yon koleksyon ki gen eleman yo rekipere sou yon baz LIFO "dènye antre, premye soti".

Keu se yon koleksyon ki gen eleman yo jwenn dapre prensip ("premye antre, premye soti" FIFO

Oke, ann kontinye.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

JavaScript se yon langaj pwogramasyon yon sèl-threaded. Sa vle di ke li gen sèlman yon fil nan ekzekisyon ak yon sèl chemine kote fonksyon yo nan keu pou ekzekisyon. Se poutèt sa, JavaScript ka sèlman fè yon operasyon nan yon moman, pandan y ap lòt operasyon yo ap tann vire yo sou chemine a jiskaske yo rele yo.

Rele pile se yon estrikti done ki, an tèm senp, anrejistre enfòmasyon sou plas nan pwogram kote nou ye a. Si nou vole nan yon fonksyon, nou pouse antre li nan tèt chemine a. Lè nou retounen soti nan yon fonksyon, nou pete eleman ki pi wo nan chemine a epi fini kote nou rele fonksyon sa a soti. Se tout sa pile a ka fè. Epi, koulye a yon kesyon trè enteresan. Lè sa a, ki jan asynchrony travay nan JavasScript?

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

An reyalite, anplis pile a, navigatè yo gen yon keu espesyal pou travay ak sa yo rele WebAPI. Fonksyon ki soti nan keu sa a pral egzekite nan lòd sèlman apre pil la konplètman otorize. Se sèlman apre sa yo mete yo soti nan keu la sou chemine a pou ekzekisyon. Si gen omwen yon eleman sou pil la nan moman sa a, Lè sa a, yo pa ka jwenn sou pil la. Jis poutèt sa, apèl fonksyon pa timeout souvan pa kòrèk nan tan, depi fonksyon an pa ka soti nan keu la nan chemine a pandan li plen.

Ann pran yon gade nan egzanp sa a epi ann ale nan li etap pa etap. Ann wè tou sa k ap pase nan sistèm nan.

console.log('Hi');
setTimeout(function cb1() {
    console.log('cb1');
}, 5000);
console.log('Bye');

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

1) Jiska prezan anyen pa rive. Konsole navigatè a pwòp, pil apèl la vid.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

2) Lè sa a, lòd console.log('Hi') ajoute nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

3) Epi li rive vre

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

4) Lè sa a, console.log('Hi') retire nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

5) Kounye a, ann ale nan lòd setTimeout(fonksyon cb1() {… }). Li ajoute nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

6) Kòmandman setTimeout(fonksyon cb1() {… }) egzekite. Navigatè a kreye yon revèy ki fè pati API Web la. Li pral fè yon dekont.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

7) Kòmandman setTimeout(fonksyon cb1() {… }) fini travay li epi yo retire li nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

8) Yo ajoute kòmandman console.log('Bye') nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

9) Kòmand console.log('Bye') egzekite.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

10) Yo retire lòd console.log('Bye') nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

11) Apre omwen 5000ms pase, revèy la fini epi li mete callback CB1 la nan keu callback la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

12) Bouk evènman an pran fonksyon cb1 nan keu apèl la epi pouse l sou pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

13) Fonksyon cb1 la egzekite epi ajoute console.log('cb1') nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

14) Kòmand console.log('cb1') egzekite.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

15) Yo retire lòd console.log('cb1') nan pil apèl la.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

16) Fonksyon cb1 retire nan pil apèl la.

Ann gade nan yon egzanp nan dinamik:

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Oke, nou te gade ki jan asynchrony aplike nan JavaScript. Koulye a, ann pale yon ti tan sou evolisyon kòd asynchrone.

Evolisyon kòd asynchrone.

a(function (resultsFromA) {
    b(resultsFromA, function (resultsFromB) {
        c(resultsFromB, function (resultsFromC) {
            d(resultsFromC, function (resultsFromD) {
                e(resultsFromD, function (resultsFromE) {
                    f(resultsFromE, function (resultsFromF) {
                        console.log(resultsFromF);
                    })
                })
            })
        })
    })
});

Asynchrone pwogramasyon jan nou konnen li nan JavaScript ka fèt sèlman ak fonksyon. Yo ka pase tankou nenpòt lòt varyab nan lòt fonksyon. Men ki jan callbacks te fèt. Epi li fre, amizan ak fervan, jiskaske li tounen tristès, melankoli ak tristès. Poukisa? Wi, li senp:

  • Kòm konpleksite nan kòd la ap grandi, pwojè a byen vit vire nan fènwa plizyè blòk enbrike - "callback lanfè".
  • Manyen erè ka fasil neglije.
  • Ou pa ka retounen ekspresyon ak retounen.

Ak avènement de Promise, sitiyasyon an vin yon ti kras pi bon.

new Promise(function(resolve, reject) {
    setTimeout(() => resolve(1), 2000);

}).then((result) => {
    alert(result);
    return result + 2;

}).then((result) => {
    throw new Error('FAILED HERE');
    alert(result);
    return result + 2;

}).then((result) => {
    alert(result);
    return result + 2;

}).catch((e) => {
    console.log('error: ', e);
});

  • Chenn pwomès parèt, ki amelyore lizibilite nan kòd la
  • Te gen yon metòd separe pou entèsepte erè
  • Ekzekisyon paralèl ak Promise.all te ajoute
  • Nou ka rezoud enbrike asynchrony ak async/wait

Men, pwomès la gen limit li yo. Pou egzanp, yon pwomès, san yo pa danse ak yon tanbourin, pa ka anile, ak pi enpòtan, li travay ak yon valè.

Oke, isit la nou yo san pwoblèm apwoche pwogram reyaktif. Fatige? Oke, bon bagay la se, ou ka ale nan melanje kèk goelan, brase lide epi retounen li plis. E map kontinye.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Programmasyon reyaktif - yon paradigm pwogram ki konsantre sou koule done ak pwopagasyon chanjman yo. Ann pran yon gade pi pre nan ki sa yon kouran done ye.

// Получаем ссылку на элемент
const input = ducument.querySelector('input');

const eventsArray = [];

// Пушим каждое событие в массив eventsArray
input.addEventListener('keyup',
    event => eventsArray.push(event)
);

Ann imajine ke nou gen yon jaden D '. Nou kreye yon etalaj, ak pou chak keyup nan evènman an opinyon, nou pral estoke evènman an nan etalaj nou an. An menm tan an, mwen ta renmen sonje ke etalaj nou an klase pa tan, i.e. endèks la nan evènman pita pi gran pase endèks la nan evènman pi bonè. Yon etalaj sa a se yon modèl koule done senplifye, men li poko yon koule. Nan lòd pou etalaj sa a yo dwe san danje rele yon kouran, li dwe kapab yon jan kanmenm enfòme abonnés ke nouvo done te rive nan li. Se konsa nou rive nan definisyon koule.

Done kouran

const { interval } = Rx;
const { take } = RxOperators;

interval(1000).pipe(
    take(4)
)

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Flow se yon etalaj done ki klase pa tan ki ka endike ke done yo te chanje. Koulye a, imajine ki jan li vin pratik pou ekri kòd kote ou bezwen deklanche plizyè evènman nan diferan pati nan kòd la pou yon aksyon. Nou tou senpleman abònman nan kouran an epi li pral di nou lè chanjman rive. Ak bibliyotèk la RxJs ka fè sa.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

RxJS se yon bibliyotèk pou travay ak pwogram asynchrone ak evènman ki baze sou lè l sèvi avèk sekans obsèvab. Bibliyotèk la bay kalite prensipal la Obsèvab, plizyè kalite asistan (Obsèvatè, Orè, Sijè) ak operatè pou travay ak evènman tankou ak koleksyon (kat jeyografik, filtre, diminye, chak ak sa ki sanble nan JavaScript Array).

Ann konprann konsèp debaz bibliyotèk sa a.

Obsèvab, Obsèvatè, Pwodiktè

Obsèvab se premye kalite baz nou pral gade. Klas sa a gen pati prensipal aplikasyon RxJs la. Li asosye ak yon kouran obsèvab, ki ka abònman lè l sèvi avèk metòd la abònman.

Observable aplike yon mekanis oksilyè pou kreye mizajou, sa yo rele Obsèvatè. Yo rele sous valè pou yon Obsèvatè Pwodiktè. Li kapab yon etalaj, yon iteratè, yon priz entènèt, kèk kalite evènman, elatriye. Se konsa, nou ka di ke obsèvab se yon kondiktè ant Pwodiktè ak Obsèvatè.

Observable okipe twa kalite evènman Obsèvatè:

  • pwochen - nouvo done
  • erè - yon erè si sekans la sispann akòz yon eksepsyon. evènman sa a tou implique nan fen sekans lan.
  • konplè - yon siyal sou fen sekans lan. Sa vle di p ap gen nouvo done ankò

Ann wè yon demonstrasyon:

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Nan kòmansman an nou pral trete valè yo 1, 2, 3, epi apre 1 segonn. nou jwenn 4 epi fini fil nou an.

Panse byen fò

Lè sa a, mwen reyalize ke li te pi enteresan yo di pase ekri sou li. 😀

Abònman

Lè nou abònman nan yon kouran, nou kreye yon nouvo klas abònman, ki ba nou opsyon pou dezabònman ak metòd la koupe abònman. Nou kapab tou gwoup abònman lè l sèvi avèk metòd la ajoute. Oke, li se lojik ke nou ka degroupe fil lè l sèvi avèk retire. Metòd ajoute ak retire yo aksepte yon abònman diferan kòm opinyon. Mwen ta renmen remake ke lè nou dezabònman, nou dezabònman nan tout abònman timoun kòm si yo te rele tou metòd la dezabònman. Ale pi devan.

Kalite kouran dlo

HOT
FRÈ

Pwodiktè se kreye deyò obsèvab la
Pwodiktè se kreye andedan obsèvab

Done yo pase nan moman obsèvab la kreye
Done yo bay nan moman abònman an.

Bezwen plis lojik pou dezabòne
Thread fini pou kont li

Sèvi ak yon relasyon youn-a-anpil
Sèvi ak yon relasyon youn a youn

Tout abònman gen menm valè
Abònman yo endepandan

Done yo ka pèdi si pa gen abònman
Reemèt tout valè kouran pou yon nouvo abònman

Pou bay yon analoji, mwen ta imajine yon kouran cho tankou yon fim nan yon sinema. Nan ki pwen nan tan ou te vini, depi moman sa a ou te kòmanse gade. Mwen ta konpare yon kouran frèt ak yon apèl nan sa yo. sipò. Nenpòt moun k ap rele koute anrejistreman reponn a depi nan kòmansman rive nan fen, men ou ka rakwoche ak dezabònman.

Mwen ta renmen remake ke gen tou sa yo rele kouran dlo cho (mwen te rankontre yon definisyon konsa trè raman e sèlman nan kominote etranje yo) - sa a se yon kouran ki transfòme soti nan yon kouran frèt nan yon sèl cho. Kesyon an rive - ki kote yo sèvi ak)) Mwen pral bay yon egzanp nan pratik.

Mwen ap travay ak Angular. Li aktivman itilize rxjs. Pou jwenn done sou sèvè a, mwen espere yon kouran frèt epi mwen itilize kouran sa a nan modèl la lè l sèvi avèk asyncPipe. Si mwen sèvi ak tiyo sa a plizyè fwa, lè sa a, retounen nan definisyon an nan yon kouran frèt, chak tiyo pral mande done nan sèvè a, ki se etranj di omwen. Men, si mwen konvèti yon kouran frèt nan yon sèl cho, Lè sa a, demann lan pral rive yon fwa.

An jeneral, konprann ki kalite koule se byen difisil pou débutan, men enpòtan.

Operatè

return this.http.get(`${environment.apiUrl}/${this.apiUrl}/trade_companies`)
    .pipe(
        tap(({ data }: TradeCompanyList) => this.companies$$.next(cloneDeep(data))),
        map(({ data }: TradeCompanyList) => data)
    );

Operatè yo bay nou yon opòtinite pou travay ak kouran. Yo ede kontwole evènman yo ap koule tankou dlo nan Observable a. Nou pral konsidere yon koup nan sa yo ki pi popilè, ak plis enfòmasyon sou operatè yo ka jwenn nan lyen yo nan enfòmasyon itil.

Operatè-of

Ann kòmanse ak operatè asistan an nan. Li kreye yon Obsèvab ki baze sou yon valè senp.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè-filtre

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè filtre a, jan non an sijere, filtre siyal kouran an. Si operatè a retounen vre, Lè sa a, li sote pi lwen.

Operatè - pran

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

pran - Pran valè kantite emèt, apre sa kouran an fini.

Operatè-debounceTime

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

debounceTime - jete valè emèt ki tonbe nan entèval tan espesifye ant done pwodiksyon - apre entèval tan an pase, emèt dènye valè a.

const { Observable } = Rx;
const { debounceTime, take } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  observer.next(i++);
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++)
  }, 1000);

 // Испускаем значение раз в 1500мс
  setInterval(() => {
    observer.next(i++)
  }, 1500);
}).pipe(
  debounceTime(700),  // Ожидаем 700мс значения прежде чем обработать
  take(3)
);  

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè-takeWhile

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Emèt valè jiskaske takeWhile retounen fo, Lè sa a, dezabònman nan kouran an.

const { Observable } = Rx;
const { debounceTime, takeWhile } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  observer.next(i++);
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++)
  }, 1000);
}).pipe(
  takeWhile( producer =>  producer < 5 )
);  

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè-konbineDènye

Operatè konbine combineLatest se yon ti jan menm jan ak promise.all. Li konbine plizyè kouran nan yon sèl. Apre chak fil te fè omwen yon emèt, nou jwenn dènye valè yo nan chak kòm yon etalaj. Pli lwen, apre nenpòt ki emèt soti nan kouran yo konbine, li pral bay nouvo valè.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

const { combineLatest, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
});

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750мс
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
});

combineLatest(observer_1, observer_2).pipe(take(5));

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè-zip

Zip - tann yon valè nan chak kouran epi fòme yon etalaj ki baze sou valè sa yo. Si valè a pa soti nan nenpòt fil, Lè sa a, gwoup la pa pral fòme.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

const { zip, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
});

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
});

const observer_3 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 500
  setInterval(() => {
    observer.next('c: ' + i++);
  }, 500);
});

zip(observer_1, observer_2, observer_3).pipe(take(5));

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè yo - forkJoin

forkJoin tou rantre nan fil, men li sèlman emèt yon valè lè tout fil yo konplè.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

const { forkJoin, Observable } = Rx;
const { take } = RxOperators;

const observer_1 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next('a: ' + i++);
  }, 1000);
}).pipe(take(3));

const observer_2 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 750
  setInterval(() => {
    observer.next('b: ' + i++);
  }, 750);
}).pipe(take(5));

const observer_3 = Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 500
  setInterval(() => {
    observer.next('c: ' + i++);
  }, 500);
}).pipe(take(4));

forkJoin(observer_1, observer_2, observer_3);

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè-kat jeyografik

Operatè transfòmasyon kat jeyografik la transfòme valè emèt nan yon nouvo.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

const {  Observable } = Rx;
const { take, map } = RxOperators;

Observable.create((observer) => {
  let i = 1;
  // Испускаем значение раз в 1000мс
  setInterval(() => {
    observer.next(i++);
  }, 1000);
}).pipe(
  map(x => x * 10),
  take(3)
);

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè yo - pataje, tape

Operatè tiyo a pèmèt ou fè efè segondè, se sa ki, nenpòt aksyon ki pa afekte sekans lan.

Operatè sèvis piblik pataje ka vire yon kouran frèt nan yon kouran cho.

Programmation asynchrone nan JavaScript (Callback, Promise, RxJs)

Operatè yo fini. Ann ale nan Sijè.

Panse byen fò

Apre sa, mwen te ale nan bwè te. Mwen bouke ak egzanp sa yo 😀

Sijè fanmi

Fanmi sijè a se yon premye egzanp nan fil cho. Klas sa yo se yon kalite ibrid ki aji kòm obsèvatè ak obsèvatè an menm tan. Depi sijè a se yon kouran cho, li dwe dezabòne nan. Si nou pale sou metòd prensipal yo, sa yo se:

  • pwochen - pase nouvo done nan kouran an
  • erè - erè ak revokasyon fil
  • konplè - fen fil la
  • abònman - abònman nan yon kouran
  • unsubscribe - dezabònman nan fil la
  • asObservable - transfòme nan yon obsèvatè
  • toPromise - transfòme nan yon pwomès

Atribye 4 5 kalite matyè.

Panse byen fò

Mwen te di 4 sou kouran an, men li te tounen soti yo te ajoute yon lòt. Jan pwovèb la di, viv epi aprann.

Sijè senp new Subject()- kalite ki pi senp nan matyè yo. Kreye san paramèt. Pase valè yo ki te vini sèlman apre abònman an.

Konpòtman Sijè new BehaviorSubject( defaultData<T> ) - nan opinyon mwen kalite ki pi komen nan sijè-s. Antre a pran valè default la. Toujou sove done yo nan dènye pwoblèm nan, ki se transmèt lè abònman. Klas sa a tou gen yon metòd valè itil ki retounen valè aktyèl la nan kouran an.

ReplaySubject new ReplaySubject(bufferSize?: number, windowTime?: number) - Opsyonèlman, li ka pran kòm premye agiman gwosè a nan tanpon nan valè ke li pral estoke nan tèt li, ak dezyèm fwa a pandan ke nou bezwen chanjman.

asyncsubject new AsyncSubject() - pa gen anyen k ap pase lè w abònman, epi valè a pral retounen sèlman lè w fin ranpli. Se sèlman dènye valè kouran an ap retounen.

WebSocketSubject new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) - Dokiman an silans sou li e mwen menm mwen wè li pou premye fwa. Ki moun ki konnen sa li fè, ekri, nou pral ajoute.

Ouf. Oke, nou te konsidere tout sa mwen te vle di jodi a. Espere enfòmasyon sa a te itil. Ou ka li lis literati a poukont ou nan tab Enfòmasyon ki itil.

enfòmasyon itil

Sous: www.habr.com

Add nouvo kòmantè