Sveiki visiem. Sergejs OmeļÅickis sazinÄs. Pirms neilga laika es uzÅÄmu straumi par reaktÄ«vo programmÄÅ”anu, kurÄ es runÄju par asinhroniju JavaScript. Å odien es vÄlÄtos veikt piezÄ«mes par Å”o materiÄlu.
Bet pirms mÄs sÄkam galveno materiÄlu, mums ir jÄizdara ievada piezÄ«me. TÄtad, sÄksim ar definÄ«cijÄm: kas ir kaudze un rinda?
Kaudze ir kolekcija, kuras elementi tiek iegūti, pamatojoties uz LIFO principu
Rinda ir kolekcija, kuras elementi iegÅ«ti pÄc FIFO principa āpirmais iekÅ”Ä, pirmais ÄrÄā.
Labi, turpinÄsim.
JavaScript ir viena pavediena programmÄÅ”anas valoda. Tas nozÄ«mÄ, ka ir tikai viens izpildes pavediens un viens steks, kurÄ funkcijas tiek ievietotas izpildes rindÄ. TÄpÄc JavaScript vienlaikus var veikt tikai vienu darbÄ«bu, savukÄrt citas darbÄ«bas gaidÄ«s savu kÄrtu stekÄ, lÄ«dz tÄs tiks izsauktas.
zvanu kaudze ir datu struktÅ«ra, kas, vienkÄrÅ”i sakot, ieraksta informÄciju par vietu programmÄ, kur mÄs atrodamies. Ja mÄs pÄrejam uz funkciju, mÄs virzÄm tÄs ievadi uz kaudzes augÅ”daļu. Atgriežoties no funkcijas, mÄs izceļam augÅ”Äjo elementu no kaudzes un nonÄkam atpakaļ vietÄ, kur nosaucÄm funkciju. Tas ir viss, ko kaudze var darÄ«t. Un tagad ÄrkÄrtÄ«gi interesants jautÄjums. KÄ tad asinhronija darbojas JavaScript?
Faktiski, papildus kaudzei, pÄrlÅ«kprogrammÄm ir Ä«paÅ”a rinda darbam ar tÄ saukto WebAPI. Funkcijas Å”ajÄ rindÄ tiks izpildÄ«tas kÄrtÄ«bÄ tikai pÄc tam, kad steka bÅ«s pilnÄ«bÄ notÄ«rÄ«ta. Tikai pÄc tam tie tiek nospiesti no rindas uz steku izpildei. Ja kaudzÄ Å”obrÄ«d ir vismaz viens elements, tad tos nevar pievienot stekam. TieÅ”i Ŕī iemesla dÄļ funkciju izsaukÅ”ana pÄc taimauta bieži vien nav precÄ«za laikÄ, jo funkcija nevar nokļūt no rindas uz steku, kamÄr tÄ ir pilna.
ApskatÄ«sim Å”o piemÄru un sÄksim ar tÄ soli pa solim izpildi. PaskatÄ«simies arÄ«, kas notiek sistÄmÄ.
1) PagaidÄm nekas nenotiek. PÄrlÅ«ka konsole ir skaidra, zvanu steka ir tukÅ”a.
2) PÄc tam komanda console.log('Hi') tiek pievienota zvanu stekam.
3) Un tas ir izpildīts
4) PÄc tam console.log('Hi') tiek noÅemts no zvanu steka.
5) Tagad pÄrejiet uz komandu setTimeout (funkcija cb1() {ā¦ }). Tas tiek pievienots zvanu stekam.
6) Tiek izpildÄ«ta komanda setTimeout(function cb1() {ā¦ }). PÄrlÅ«kprogramma izveido taimeri, kas ir daļa no Web API. Tas veiks atpakaļskaitÄ«Å”anu.
7) komanda setTimeout(function cb1() {... }) ir pabeigusi savu darbu un tiek noÅemta no izsaukuma steka.
8) Izsaukuma stekam tiek pievienota komanda console.log('Bye').
9) Tiek izpildīta komanda console.log('Bye').
10) Komanda console.log('Bye') tiek noÅemta no zvanu steka.
11) Kad ir pagÄjuÅ”i vismaz 5000 ms, taimeris pÄrtrauc darbÄ«bu un ievieto atzvanÄ«Å”anas cb1 atzvanÄ«Å”anas rindÄ.
12) Notikuma cilpa paÅem funkciju cb1 no atzvanÄ«Å”anas rindas un ievieto to zvanu stekÄ.
13) Funkcija cb1 tiek izpildīta un pievieno console.log('cb1') izsaukuma stekam.
14) Tiek izpildīta komanda console.log('cb1').
15) Komanda console.log('cb1') tiek noÅemta no izsaukumu steka.
16) Funkcija cb1 tiek noÅemta no zvanu steka.
ApskatÄ«sim piemÄru dinamikÄ:
MÄs apskatÄ«jÄm, kÄ JavaScript tiek ieviesta asinhronija. Tagad Ä«si parunÄsim par asinhronÄ koda attÄ«stÄ«bu.
AsinhronÄ koda attÄ«stÄ«ba.
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);
})
})
})
})
})
});
Asinhrono programmÄÅ”anu, kÄdu mÄs to zinÄm JavaScript, var ieviest tikai ar funkcijÄm. Tos tÄpat kÄ jebkuru citu mainÄ«go var nodot citÄm funkcijÄm. TÄ radÄs atzvani. Un tas ir forÅ”i, jautri un rotaļīgi, lÄ«dz pÄrvÄrÅ”as skumjÄs, melanholijÄ un skumjÄs. KÄpÄc? Tas ir vienkÄrÅ”i:
LÄ«dz ar solÄ«juma parÄdÄ«Å”anos situÄcija kļuva nedaudz labÄka.
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);
});
ParÄdÄ«jÄs solÄ«jumu Ä·Ädes, kas uzlaboja koda lasÄmÄ«bu
Ir parÄdÄ«jusies atseviŔķa metode kļūdu uztverÅ”anai
Pievienota paralÄlas izpildes iespÄja, izmantojot Promise.all
MÄs varam atrisinÄt ligzdoto asinhroniju, izmantojot async/await
TaÄu solÄ«jumiem ir savi ierobežojumi. PiemÄram, solÄ«jumu nevar atcelt, nedejojot ar tamburÄ«nu, un vissvarÄ«gÄkais ir tas, ka tas darbojas ar vienu vÄrtÄ«bu.
Nu, mÄs esam gludi pietuvojuÅ”ies reaktÄ«vai programmÄÅ”anai. Noguris? Par laimi, jÅ«s varat doties uzvÄrÄ«t tÄju, padomÄt par to un atgriezties, lai lasÄ«tu vairÄk. Un es turpinÄÅ”u.
ReaktÄ«vÄ programmÄÅ”anaāir programmÄÅ”anas paradigma, kas vÄrsta uz datu plÅ«smÄm un izmaiÅu izplatÄ«Å”anu. SÄ«kÄk apskatÄ«sim, kas ir datu straume.
IedomÄsimies, ka mums ir ievades lauks. MÄs veidojam masÄ«vu, un katram ievades notikuma taustiÅam mÄs saglabÄsim notikumu savÄ masÄ«vÄ. TajÄ paÅ”Ä laikÄ vÄlos atzÄ«mÄt, ka mÅ«su masÄ«vs ir sakÄrtots pÄc laika, t.i. vÄlÄko notikumu indekss ir lielÄks nekÄ agrÄko notikumu indekss. Å Äds masÄ«vs ir vienkÄrÅ”ots datu plÅ«smas modelis, taÄu tas vÄl nav plÅ«sma. Lai Å”o masÄ«vu varÄtu droÅ”i saukt par straumi, tam ir jÄspÄj kaut kÄdÄ veidÄ informÄt abonentus, ka tajÄ ir ienÄkuÅ”i jauni dati. TÄdÄjÄdi mÄs nonÄkam pie plÅ«smas definÄ«cijas.
PlÅ«smaāir datu masÄ«vs, kas sakÄrtots pÄc laika un var norÄdÄ«t, ka dati ir mainÄ«juÅ”ies. Tagad iedomÄjieties, cik Ärti kļūst rakstÄ«t kodu, kurÄ vienai darbÄ«bai ir nepiecieÅ”ams izsaukt vairÄkus notikumus dažÄdÄs koda daļÄs. MÄs vienkÄrÅ”i abonÄjam straumi, un tÄ mums paziÅos, kad notiks izmaiÅas. Un RxJs bibliotÄka to var izdarÄ«t.
RxJS ir bibliotÄka darbam ar asinhronÄm un uz notikumiem balstÄ«tÄm programmÄm, izmantojot novÄrojamas secÄ«bas. BibliotÄka nodroÅ”ina pamata veidu NovÄrojams, vairÄki papildu veidi (NovÄrotÄjs, PlÄnotÄji, Subjekti) un operatori darbam ar pasÄkumiem kÄ ar kolekcijÄm (kartÄt, filtrÄt, samazinÄt, katru un lÄ«dzÄ«gas no JavaScript masÄ«va).
IzpratÄ«sim Ŕīs bibliotÄkas pamatjÄdzienus.
VÄrojams, novÄrotÄjs, producents
NovÄrojamais ir pirmais pamata veids, ko mÄs apskatÄ«sim. Å ajÄ klasÄ ir galvenÄ RxJs ievieÅ”anas daļa. Tas ir saistÄ«ts ar novÄrojamu straumi, kuru var abonÄt, izmantojot abonÄÅ”anas metodi.
Observable ievieÅ” palÄ«gmehÄnismu atjauninÄjumu izveidei, tÄ saukto NovÄrotÄjs. Tiek saukts novÄrotÄja vÄrtÄ«bu avots Producents. Tas varÄtu bÅ«t masÄ«vs, iterators, tÄ«mekļa ligzda, kÄds notikums utt. TÄtad mÄs varam teikt, ka novÄrojamais ir diriÄ£ents starp producentu un novÄrotÄju.
Observable apstrÄdÄ trÄ«s veidu Observer notikumus:
pabeigts ā signÄls par secÄ«bas pabeigÅ”anu. Tas nozÄ«mÄ, ka jaunu datu vairs nebÅ«s.
ApskatÄ«sim demonstrÄciju:
SÄkumÄ mÄs apstrÄdÄsim vÄrtÄ«bas 1, 2, 3 un pÄc 1 sekundes. mÄs saÅemsim 4 un beigsim mÅ«su straumi.
Skaļi domÄjot
Un tad es sapratu, ka stÄstÄ«t ir interesantÄk nekÄ rakstÄ«t par to. š
AbonÄÅ”ana
Kad abonÄjam straumi, mÄs izveidojam jaunu klasi abonementskas dod mums iespÄju anulÄt abonementu, izmantojot metodi atrakstÄ«ties. MÄs varam arÄ« grupÄt abonementus, izmantojot metodi pievienot. Ir loÄ£iski, ka mÄs varam atgrupÄt pavedienus, izmantojot noÅemt. PievienoÅ”anas un noÅemÅ”anas metodes kÄ ievadi pieÅem citu abonementu. Es vÄlos atzÄ«mÄt, ka, anulÄjot abonementu, mÄs anulÄjam visus bÄrnu abonementus, it kÄ viÅi bÅ«tu izsaukuÅ”i abonÄÅ”anas atcelÅ”anas metodi. Uz priekÅ”u.
Straumju veidi
HOT
Auksts
Producents ir izveidots Ärpus novÄrojama
Producents ir izveidots iekÅ”Ä novÄrojams
Dati tiek pÄrsÅ«tÄ«ti brÄ«dÄ«, kad tiek izveidots novÄrojums
Dati tiek sniegti abonÄÅ”anas brÄ«dÄ«
NepiecieÅ”ama papildu loÄ£ika abonÄÅ”anas atcelÅ”anai
VÄ«tne beidzas pati no sevis
Izmanto attiecības viens pret daudziem
Izmanto attiecības viens pret vienu
Visiem abonementiem ir vienÄda nozÄ«me
Abonementi ir neatkarīgi
Dati var tikt zaudÄti, ja jums nav abonementa
AtkÄrtoti izdod visas straumes vÄrtÄ«bas jaunam abonementam
Lai sniegtu analoÄ£iju, es domÄju par karstu straumi kÄ filmu teÄtrÄ«. KurÄ brÄ«dÄ« jÅ«s ieradÄties, no Ŕī brīža jÅ«s sÄkÄt skatÄ«ties. Es salÄ«dzinÄtu aukstu plÅ«smu ar zvanu tehnoloÄ£iju jomÄ. atbalsts. JebkurÅ” zvanÄ«tÄjs noklausÄs balss pasta ierakstu no sÄkuma lÄ«dz beigÄm, taÄu jÅ«s varat pÄrtraukt klausuli, izmantojot anulÄt abonementu.
VÄlos atzÄ«mÄt, ka ir arÄ« tÄ saucamÄs siltÄs plÅ«smas (ar Å”o definÄ«ciju esmu sastapies ÄrkÄrtÄ«gi reti un tikai Ärzemju kopienÄs) - Ŕī ir plÅ«sma, kas no aukstÄs plÅ«smas pÄrvÄrÅ”as karstÄ. Rodas jautÄjums - kur izmantot)) Es sniegÅ”u piemÄru no prakses.
Es strÄdÄju ar Angular. ViÅÅ” aktÄ«vi izmanto rxjs. Lai saÅemtu datus serverÄ«, es sagaidu aukstu pavedienu un izmantoju Å”o pavedienu veidnÄ, izmantojot asyncPipe. Ja es izmantoju Å”o cauruli vairÄkas reizes, tad, atgriežoties pie aukstÄs straumes definÄ«cijas, katra caurule pieprasÄ«s datus no servera, kas ir maigi izsakoties dÄ«vaini. Un, ja es pÄrvÄrÅ”u aukstu straumi siltÄ, tad pieprasÄ«jums notiks vienu reizi.
KopumÄ iesÄcÄjiem ir diezgan grÅ«ti saprast plÅ«smu veidu, taÄu tas ir svarÄ«gi.
UzÅÄmÄjiem
return this.http.get(`${environment.apiUrl}/${this.apiUrl}/trade_companies`)
.pipe(
tap(({ data }: TradeCompanyList) => this.companies$$.next(cloneDeep(data))),
map(({ data }: TradeCompanyList) => data)
);
Operatori nodroÅ”ina mums iespÄju paplaÅ”inÄt mÅ«su iespÄjas strÄdÄt ar straumÄm. Tie palÄ«dz kontrolÄt notikumus, kas notiek novÄrojamajÄ. ApskatÄ«sim pÄris populÄrÄkos, un sÄ«kÄku informÄciju par operatoriem var atrast, izmantojot noderÄ«gajÄ informÄcijÄ esoÅ”Äs saites.
Operatori - no
SÄksim ar palÄ«goperatoru. Tas izveido novÄrojamo, pamatojoties uz vienkÄrÅ”u vÄrtÄ«bu.
Operatori - filtrs
Filtra operators, kÄ norÄda nosaukums, filtrÄ straumes signÄlu. Ja operators atgriež true, tas izlaiž tÄlÄk.
Operatori - Åemiet
take ā Åem izstarotÄju skaita vÄrtÄ«bu, pÄc kura vÄ«tne beidzas.
Operatori ā debounceTime
debounceTime - atmet izstarotÄs vÄrtÄ«bas, kas ietilpst norÄdÄ«tajÄ laika intervÄlÄ starp izvadÄm - pÄc laika intervÄla beigÄm izstaro pÄdÄjo vÄrtÄ«bu.
CombinLatest operators ir nedaudz lÄ«dzÄ«gs solÄ«dam.all. Tas apvieno vairÄkus pavedienus vienÄ. PÄc tam, kad katrs pavediens veic vismaz vienu emisiju, mÄs iegÅ«stam jaunÄkÄs vÄrtÄ«bas no katra masÄ«va veidÄ. TurklÄt pÄc jebkÄdas emisijas no apvienotajÄm plÅ«smÄm tas dos jaunas vÄrtÄ«bas.
Zip ā gaida vÄrtÄ«bu no katra pavediena un veido masÄ«vu, pamatojoties uz Ŕīm vÄrtÄ«bÄm. Ja vÄrtÄ«ba nenÄk no neviena pavediena, grupa netiks izveidota.
PieskarÅ”anÄs operators ļauj veikt blakusparÄdÄ«bas, tas ir, jebkuras darbÄ«bas, kas neietekmÄ secÄ«bu.
DalÄ«Å”anas utilÄ«ta operators var pÄrvÄrst aukstu straumi karstÄ.
Esam pabeiguÅ”i darbu ar operatoriem. PÄrejam pie tÄmas.
Skaļi domÄjot
Un tad es devos iedzert tÄju. Man ir apnikuÅ”i Å”ie piemÄri š
PriekŔmeta ģimene
PriekÅ”meta saime ir lielisks karsto plÅ«smu piemÄrs. Å Ä«s klases ir sava veida hibrÄ«ds, kas vienlaikus darbojas kÄ novÄrojams un novÄrotÄjs. TÄ kÄ tÄma ir aktuÄla, ir jÄatsakÄs no tÄ abonÄÅ”anas. Ja mÄs runÄjam par galvenajÄm metodÄm, tad tÄs ir:
nÄkamais ā jaunu datu pÄrsÅ«tÄ«Å”ana uz straumi
kļūda ā kļūda un pavediena pÄrtraukÅ”ana
pabeigt ā pavediena pabeigÅ”ana
abonÄt ā abonÄt straumi
atteikties no straumes abonÄÅ”anas
asObservable ā pÄrveidoties par novÄrotÄju
toPromise ā pÄrvÄrÅ”as par solÄ«jumu
Ir 4 5 priekŔmetu veidi.
Skaļi domÄjot
StraumÄ runÄja 4 cilvÄki, bet izrÄdÄ«jÄs, ka viÅi pievienoja vÄl vienu. KÄ saka, dzÄ«vo un mÄcies.
VienkÄrÅ”s priekÅ”mets new Subject()ā vienkÄrÅ”Äkais priekÅ”metu veids. Izveidots bez parametriem. PÄrsÅ«ta vÄrtÄ«bas, kas saÅemtas tikai pÄc abonÄÅ”anas.
BehaviorSubject new BehaviorSubject( defaultData<T> ) ā manuprÄt, visizplatÄ«tÄkais priekÅ”meta veids. Ievade iegÅ«st noklusÄjuma vÄrtÄ«bu. VienmÄr saglabÄ pÄdÄjÄ numura datus, kas tiek pÄrsÅ«tÄ«ti abonÄÅ”anas laikÄ. Å ai klasei ir arÄ« noderÄ«ga vÄrtÄ«bu metode, kas atgriež straumes paÅ”reizÄjo vÄrtÄ«bu.
Replay Subject new ReplaySubject(bufferSize?: number, windowTime?: number) ā Ievade pÄc izvÄles var izmantot kÄ pirmo argumentu vÄrtÄ«bu bufera lielumu, ko tÄ saglabÄs sevÄ«, un kÄ otro argumentu, kurÄ mums ir nepiecieÅ”amas izmaiÅas.
AsyncSubject new AsyncSubject() ā abonÄÅ”anas laikÄ nekas nenotiek, un vÄrtÄ«ba tiks atgriezta tikai tad, kad tÄ bÅ«s pabeigta. Tiks atgriezta tikai pÄdÄjÄ straumes vÄrtÄ«ba.
WebSocketSubject new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) ā DokumentÄcija par viÅu klusÄ, un es viÅu redzu pirmo reizi. Ja kÄds zina ar ko viÅÅ” nodarbojas, lÅ«dzu rakstiet un mÄs pievienosim.
FÅ«. MÄs esam apskatÄ«juÅ”i visu, ko es Å”odien gribÄju jums pastÄstÄ«t. Ceru, ka Ŕī informÄcija bija noderÄ«ga. AtsauÄu sarakstu varat izlasÄ«t pats noderÄ«gas informÄcijas cilnÄ.