Pemrograman asinkron ing JavaScript (Callback, Promise, RxJs)
Halo kabeh. Ing tutul Omelnitsky Sergey. Ora suwe, aku dadi tuan rumah stream babagan program reaktif, ing ngendi aku ngomong babagan asinkron ing JavaScript. Dina iki aku arep ngringkes materi iki.
Nanging sadurunge miwiti materi utama, kita kudu nggawe introduksi. Dadi ayo miwiti karo definisi: apa tumpukan lan antrian?
tumpukan yaiku koleksi sing unsur-unsur kasebut dipikolehi kanthi basis LIFO pungkasan, pisanan metu
Saiki minangka koleksi sing unsur dijupuk kanthi basis FIFO pisanan-in, metu pisanan
Oke, ayo nerusake.
JavaScript minangka basa pamrograman siji-threaded. Tegese mung ana siji utas eksekusi lan siji tumpukan sing fungsine antri kanggo eksekusi. Mulane, JavaScript mung bisa nindakake siji operasi ing wektu, nalika operasi liyane bakal ngenteni giliran ing tumpukan nganti padha disebut.
Telpon tumpukan minangka struktur data sing, kanthi prasaja, nyathet informasi babagan panggonan ing program ing ngendi kita. Yen kita mlumpat menyang fungsi, kita push entri menyang ndhuwur tumpukan. Nalika kita bali saka fungsi, kita pop unsur paling ndhuwur saka tumpukan lan mungkasi munggah ngendi kita disebut fungsi iki saka. Sing kabeh tumpukan bisa nindakake. Lan saiki pitakonan sing menarik banget. Kepiye carane ora sinkron ing JavasScript?
Nyatane, saliyane tumpukan, browser duwe antrian khusus kanggo nggarap WebAPI sing disebut. Fungsi ing antrian iki bakal kaleksanan ing urutan mung sawise tumpukan wis rampung ngankat. Mung sawise iki di-push saka antrian menyang tumpukan kanggo eksekusi. Yen ana ing paling siji unsur ing tumpukan ing wayahe, banjur padha ora bisa ditambahake kanggo tumpukan. Iku sabenere amarga iki sing nelpon fungsi dening wektu entek asring ora pas wektu, wiwit fungsi ora bisa njaluk saka antrian kanggo tumpukan nalika kebak.
Ayo ndeleng conto ing ngisor iki lan miwiti implementasine langkah-langkah. Ayo uga ndeleng apa sing kedadeyan ing sistem kasebut.
7) Printah setTimeout(fungsi cb1() {... }) wis rampung karya lan dibusak saka tumpukan telpon.
8) printah console.log ('Bye') ditambahake menyang tumpukan telpon.
9) printah console.log ('Bye') kaleksanan.
10) printah console.log ('Bye') dibusak saka tumpukan telpon.
11) Sawise paling ora 5000ms wis liwati, timer mungkasi lan sijine cb1 callback menyang antrian callback.
12) Daur ulang acara njupuk fungsi cb1 saka antrian callback lan dilebokake ing tumpukan telpon.
13) Fungsi cb1 dieksekusi lan nambah console.log ('cb1') menyang tumpukan telpon.
14) printah console.log ('cb1') kaleksanan.
15) printah console.log ('cb1') dibusak saka tumpukan telpon.
16) Fungsi cb1 dibusak saka tumpukan telpon.
Ayo ndeleng conto ing dinamika:
Ya, kita ndeleng kepiye asynchrony ditindakake ing JavaScript. Saiki ayo ngomong kanthi ringkes babagan evolusi kode asinkron.
Γvolusi kode asinkron.
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);
})
})
})
})
})
});
Pemrograman asinkron kaya sing kita kenal ing JavaScript mung bisa ditindakake kanthi fungsi. Padha bisa liwati kaya variabel liyane kanggo fungsi liyane. Iki carane callbacks lair. Lan kelangan, nyenengake lan nyenengake, nganti dadi sedhih, melankolis lan sedhih. Kenging punapa? Iku prasaja:
Nalika kerumitan kode mundhak, proyek kasebut kanthi cepet dadi pirang-pirang blok sing ora jelas - "neraka panggilan".
Penanganan kesalahan bisa gampang kantun.
Sampeyan ora bisa bali ekspresi karo bali.
Kanthi tekane Janji, kahanan dadi luwih apik.
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);
});
Rantai janji muncul, sing nambah keterbacaan kode
Cara sing kapisah kanggo nyekel kesalahan wis muncul
Ditambahake kamungkinan eksekusi paralel nggunakake Promise.all
Kita bisa ngatasi asynchrony nested nggunakake async/await
Nanging janji duwe watesan. Contone, janji ora bisa dibatalake tanpa nari karo rebana, lan sing paling penting, bisa digunakake kanthi nilai siji.
Inggih, ing kene kita nyedhaki program reaktif kanthi lancar. kesel? Inggih, ing bab apik, sampeyan bisa pindhah menyang brew sawetara gull , brainstorming lan bali kanggo maca liyane. Lan aku bakal terus.
Pemrograman Reaktifβminangka paradigma pemrograman sing fokus ing aliran data lan panyebaran owah-owahan. Ayo dideleng kanthi cetha babagan apa aliran data.
Alurβyaiku susunan data sing diurutake miturut wektu sing bisa nuduhake yen data kasebut wis owah. Saiki bayangake carane trep kanggo nulis kode sing siji tumindak mbutuhake nelpon sawetara acara ing macem-macem bagean kode. Kita mung langganan stream lan bakal menehi kabar yen ana owah-owahan. Lan perpustakaan RxJs bisa nindakake iki.
RxJS minangka perpustakaan kanggo nggarap program sing ora sinkron lan adhedhasar acara kanthi nggunakake urutan sing bisa diamati. Pustaka nyedhiyakake jinis dhasar Bisa dideleng, sawetara jinis tambahan (Pengamat, Penjadwal, Subyek) lan operator kanggo nggarap acara kaya koleksi (map, nyaring, nyuda, saben lan sing padha saka JavaScript Array).
Ayo padha ngerti konsep dhasar saka perpustakaan iki.
Observable, Observer, Produser
Bisa diamati minangka jinis dhasar pisanan sing bakal kita deleng. Kelas iki ngemot bagean utama saka implementasine RxJs. Iki digandhengake karo stream sing bisa diamati, sing bisa dilanggan nggunakake metode langganan.
Observable ngetrapake mekanisme tambahan kanggo nggawe nganyari, sing diarani Observer. Sumber nilai kanggo Observer diarani Produser. Bisa dadi array, iterator, soket web, sawetara acara, lsp. Dadi bisa diarani observable minangka konduktor antarane Produser lan Observer.
Observable nangani telung jinis acara Observer:
sabanjure - data anyar
kesalahan - kesalahan yen urutan rampung amarga pangecualian. acara iki uga nuduhake completion saka urutan.
lengkap - sinyal bab mburi urutan. Iki tegese ora bakal ana data anyar maneh
Ayo ndeleng demo:
Ing wiwitan, kita bakal ngolah nilai 1, 2, 3, lan sawise 1 detik. kita bakal entuk 4 lan mungkasi stream kita.
Dipikir banter
Banjur aku nyadari yen nyritakake iku luwih menarik tinimbang nulis babagan iki. π
langganan
Nalika kita langganan stream kita nggawe kelas anyar langganankang menehi kita kemampuan kanggo unsubscribe nggunakake cara Unsubscribe. Kita uga bisa klompok langganan nggunakake cara nambah. Inggih, logis yen kita bisa ungroup thread nggunakake mbusak. Cara nambah lan mbusak nampa langganan beda minangka input. Aku pengin Wigati sing nalika kita unsubscribe, kita unsubscribe saka kabeh anak lengganan minangka padha uga disebut cara unsubscribe. Terusna.
Jinis-jinis lepen
HOT
EMAS
Produser digawe ing njaba bisa diamati
Produser digawe ing jero bisa diamati
Data ditransfer nalika observasi digawe
Data diwenehake nalika langganan.
Perlu logika liyane kanggo unsubscribe
Utas mungkasi dhewe
Migunakake hubungan siji-kanggo-akeh
Migunakake hubungan siji-kanggo-siji
Kabeh langganan nduweni teges sing padha
Langganan iku sawijining
Data bisa ilang yen ora ana langganan
Nerbitake maneh kabeh nilai stream kanggo langganan anyar
Aku pengin Wigati sing ana uga disebut aliran anget (aku wis ketemu definisi iki arang banget lan mung ing masyarakat manca) - iki aliran sing ngowahi saka aliran kadhemen kanggo panas. Pitakonan muncul - ing ngendi nggunakake)) Aku bakal menehi conto saka praktik.
Aku nggarap Angular. Dheweke aktif nggunakake rxjs. Kanggo nampa data menyang server, aku nyana thread kadhemen lan nggunakake thread iki ing cithakan nggunakake asyncPipe. Yen aku nggunakake pipo iki kaping pirang-pirang, banjur, bali menyang definisi stream kadhemen, saben pipe bakal njaluk data saka server, kang aneh ngomong paling. Lan yen aku ngowahi stream kadhemen dadi anget, banjur panjalukan bakal kelakon sapisan.
return this.http.get(`${environment.apiUrl}/${this.apiUrl}/trade_companies`)
.pipe(
tap(({ data }: TradeCompanyList) => this.companies$$.next(cloneDeep(data))),
map(({ data }: TradeCompanyList) => data)
);
Operator menehi kita kemampuan kanggo nggedhekake kemampuan kanggo nggarap stream. Dheweke mbantu ngontrol acara sing kedadeyan ing Observable. Kita bakal ndeleng sawetara sing paling populer, lan rincian liyane babagan operator bisa ditemokake kanthi nggunakake tautan ing informasi sing migunani.
Operator - saka
Ayo dadi miwiti karo operator helper saka. Iku nggawe Observable adhedhasar nilai prasaja.
Operator-filter
Operator filter, kaya jenenge, nyaring sinyal stream. Yen operator bali bener, iku skip luwih.
Operator - njupuk
njupuk - Njupuk Nilai saka jumlah emits, sawise stream ends.
Operator - debounceTime
debounceTime - mbuwang nilai sing dipancarake sing ana ing interval wektu sing ditemtokake ing antarane output - sawise interval wektu wis liwati, ngetokake nilai pungkasan.
Operator combineLatest meh padha karo promise.all. Iki nggabungake pirang-pirang benang dadi siji. Sawise saben thread nggawe paling ora siji emisi, kita entuk nilai paling anyar saka saben ing wangun array. Salajengipun, sawise emisi saka aliran gabungan, bakal menehi nilai anyar.
Zip - Ngenteni nilai saka saben thread lan mbentuk array adhedhasar nilai kasebut. Yen nilai kasebut ora teka saka benang apa wae, mula grup kasebut ora bakal dibentuk.
Operator tunyuk ngidini sampeyan nindakake efek samping, yaiku, tumindak apa wae sing ora mengaruhi urutane.
Operator utilitas bareng bisa ngowahi aliran sing adhem dadi panas.
Kita wis rampung karo operator. Ayo pindhah menyang Subject.
Dipikir banter
Banjur aku lunga ngombe teh. Aku bosen karo conto-conto iki π
kulawarga subyek
Kulawarga subyek minangka conto utami saka benang panas. Kelas kasebut minangka jinis hibrida sing tumindak minangka observasi lan pengamat ing wektu sing padha. Wiwit subyek iku aliran panas, iku kudu unsubscribed saka. Yen kita ngomong babagan cara utama, iki yaiku:
sabanjure - transfer data anyar menyang stream
kesalahan - kesalahan lan mandap thread
rampung - mburi thread
langganan - langganan stream
unsubscribe β unsubscribe from the stream
asObservable - ngowahi dadi pengamat
toPromise - ngowahi dadi janji
Ana 4 5 jinis subjek.
Dipikir banter
Ana 4 wong ngomong ing stream, nanging jebule nambah siji maneh. Kaya sing dikandhakake, urip lan sinau.
Subyek prasaja new Subject()- jinis subyek sing paling gampang. Digawe tanpa paramèter. Ngirim nilai sing ditampa mung sawise langganan.
ReplaySubject new ReplaySubject(bufferSize?: number, windowTime?: number) - Input opsional bisa njupuk minangka argumen pisanan ukuran buffer saka nilai sing bakal disimpen ing dhewe, lan minangka kaloro wektu nalika kita perlu owah-owahan.
AsyncSubject new AsyncSubject() - ora ana sing kedadeyan nalika lengganan, lan regane bakal dibalekake mung yen wis rampung. Mung nilai pungkasan stream bakal bali.
WebSocketSubject new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) - Dokumentasi ora bisu babagan iki lan aku ndeleng pisanan. Yen ana sing ngerti apa sing ditindakake, tulisen lan kita bakal nambah.
Phew. Inggih, kita wis nutupi kabeh sing dakkarepake kanggo sampeyan dina iki. Mugi informasi iki migunani. Sampeyan bisa maca dhaptar referensi dhewe ing tab informasi migunani.