Ríomhchlárú asincrónach i JavaScript (Aisghlao, Gealltanas, RxJs)
Dia duit gach duine. Sergey Omelnitsky i dteagmháil. Ní chomh fada ó shin, d'óstáil mé sruth ar ríomhchlárú imoibríoch, áit ar labhair mé faoi asincrony i JavaScript. Sa lá atá inniu ba mhaith liom achoimre a dhéanamh ar an ábhar seo.
Ach sula dtosaímid ar an bpríomhábhar, ní mór dúinn réamhrá a dhéanamh. Mar sin, cuirimis tús le sainmhínithe: cad is cruacha agus scuaine ann?
Cruachán is bailiúchán é a n-aisghabhtar a ghnéithe ar bhonn LIFO “an ceann deireanach isteach, is túisce amach”.
Cas is bailiúchán é a bhfaightear a ghnéithe de réir an phrionsabail (“an chéad dul isteach, an chéad cheann amach” FIFO
Ceart go leor, a ligean ar aghaidh.
Is teanga ríomhchlárúcháin aon-snáithe í JavaScript. Ciallaíonn sé seo nach bhfuil aige ach snáithe forghníomhaithe amháin agus cruach amháin ina bhfuil feidhmeanna scuaine lena gcur i gcrích. Mar sin, ní féidir le JavaScript ach oibríocht amháin a dhéanamh ag an am, agus fanfaidh oibríochtaí eile a seal ar an gcruach go dtí go nglaofar orthu.
Stack glaonna is struchtúr sonraí é a thaifeadann, i dtéarmaí simplí, faisnéis faoin áit sa chlár ina bhfuilimid. Má léimimid isteach i bhfeidhm, brúimid a iontráil go barr an chruach. Nuair a fhilleann muid ó fheidhm, popaimid an eilimint is airde as an chairn agus deireadh suas an áit ar thug muid an fheidhm seo ó. Sin go léir is féidir leis an stack a dhéanamh. Agus anois ceist an-suimiúil. Conas mar sin a oibríonn asincrony in JavasScript?
Go deimhin, chomh maith leis an stack, tá scuaine speisialta ag brabhsálaithe chun oibriú leis an WebAPI mar a thugtar air. Ní dhéanfar feidhmeanna ón scuaine seo a fhorghníomhú in ord ach amháin tar éis don chruach a bheith glanta go hiomlán. Is ina dhiaidh sin amháin a chuirtear iad ón scuaine go dtí an chruach le cur i gcrích. Má tá eilimint amháin ar a laghad ar an gcruach faoi láthair, ní féidir leo dul ar an gcruach. Díreach mar gheall air seo, is minic a bhíonn míchruinn ag glaoch ar fheidhmeanna trí Teorainn ama, mar ní féidir leis an bhfeidhm dul ón scuaine go dtí an chruach agus é lán.
Breathnaímid ar an sampla seo a leanas agus cuirimis tús lena chur i bhfeidhm céim ar chéim. A ligean ar a fheiceáil freisin cad a tharlaíonn sa chóras.
1) Go dtí seo níl aon rud ag tarlú. Tá consól an bhrabhsálaí glan, tá an chairn glaonna folamh.
2) Ansin cuirtear an t-ordú console.log ('Dia duit') leis an gcruach glaonna.
3) Agus tá sé comhlíonta
4) Ansin baintear console.log ('Dia duit') den chruach glaonna.
5) Anois bogadh ar aghaidh go dtí an t-ordú setTimeout (feidhm cb1 () {… }). Cuirtear leis an gcruach glaonna é.
6) Déantar an t-ordú setTimeout (feidhm cb1 () {… }) a fhorghníomhú. Cruthaíonn an brabhsálaí lasc ama atá mar chuid den API Gréasáin. Déanfaidh sé comhaireamh síos.
7) Tá a chuid oibre críochnaithe ag an ordú setTimeout (feidhm cb1() {… }) agus baintear é den chruach glaonna.
8) Cuirtear an t-ordú console.log ('Bye') leis an gcruach glaonna.
9) Déantar an t-ordú console.log ('Slán') a fhorghníomhú.
10) Baintear an t-ordú console.log ('Bye') as an gcruach glaonna.
11) Tar éis ar a laghad 5000ms a bheith caite, críochnaíonn an t-amadóir agus cuireann sé an aisghlao cb1 isteach sa scuaine aisghlao.
12) Tógann lúb na hócáide feidhm cb1 ón scuaine aisghlao agus brú ar an gcruach glaonna é.
13) Déantar an fheidhm cb1 a fhorghníomhú agus cuireann sé console.log ('cb1') leis an gcruach glaonna.
14) Déantar an t-ordú console.log ('cb1') a fhorghníomhú.
15) Baintear an console command.log ('cb1') as an gcruach glaonna.
16) Baintear feidhm cb1 as an gcruach glaonna.
Breathnaímid ar shampla i ndinimic:
Bhuel, d'fhéachamar ar conas a chuirtear asincrony i bhfeidhm i JavaScript. Anois, déanaimis labhairt go hachomair faoi éabhlóid an chóid asincrónach.
Forás an chóid asincrónach.
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);
})
})
})
})
})
});
Ní féidir ríomhchlárú asincrónach mar is eol dúinn é i JavaScript a dhéanamh ach amháin le feidhmeanna. Is féidir iad a chur ar aghaidh mar aon le hathróg eile chuig feidhmeanna eile. Seo mar a rugadh glaonna ar ais. Agus tá sé fionnuar, spraoi agus fíochmhar, go dtí go n-iompaíonn sé isteach i brón, lionn dubh agus brón. Cén fáth? Sea, tá sé simplí:
De réir mar a mhéadaíonn castacht an chóid, iompaíonn an tionscadal go tapa ina ilbloic neadaithe doiléir - “ifreann aisghlaoch”.
Is féidir dearmad a dhéanamh go héasca ar láimhseáil earráidí.
Ní féidir leat slonn a chur ar ais le filleadh.
Le teacht Promise, tá an scéal tar éis éirí beagán níos fearr.
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);
});
Bhí slabhraí gealltanais le feiceáil, rud a chuir feabhas ar inléiteacht an chóid
Bhí modh ar leith ann chun earráidí a thascradh
Forghníomhú comhthreomhar le Promise.all curtha leis
Is féidir linn asincrony neadaithe a réiteach le sioncrónú/fanacht
Ach tá teorainneacha leis an ngealltanas. Mar shampla, ní féidir gealltanas, gan damhsa le tambóirín, a chur ar ceal, agus níos tábhachtaí fós, oibríonn sé le luach amháin.
Bhuel, anseo táimid ag druidim go réidh le ríomhchlárú imoibríoch. Tuirseach? Bhuel, is é an rud go maith, is féidir leat dul go dtí brew roinnt faoileáin, tobsmaointeoireachta agus filleadh ar a léamh níos mó. Agus leanfaidh mé ar aghaidh.
Cláir fhrithghníomhacha - paraidím ríomhchlárúcháin atá dírithe ar shreafaí sonraí agus ar iomadú athruithe. Breathnaímis ar cad is sruth sonraí ann.
// Получаем ссылку на элемент
const input = ducument.querySelector('input');
const eventsArray = [];
// Пушим каждое событие в массив eventsArray
input.addEventListener('keyup',
event => eventsArray.push(event)
);
Samhlóimis go bhfuil réimse ionchuir againn. Cruthaímid eagar, agus le haghaidh gach eochair den imeacht ionchuir, stórálfaimid an t-imeacht inár sraith. Ag an am céanna, ba mhaith liom a thabhairt faoi deara go ndéantar ár n-eagar a shórtáil de réir ama, i.e. tá innéacs na n-imeachtaí níos déanaí níos mó ná innéacs na n-imeachtaí níos luaithe. Is samhail sreabhadh sonraí simplithe é eagar den sórt sin, ach níl sé fós ina shreabhadh. Ionas gur féidir sruth a thabhairt ar an eagar seo go sábháilte, caithfidh sé a bheith in ann a chur in iúl do shíntiúsóirí ar bhealach éigin go bhfuil sonraí nua tagtha isteach ann. Mar sin tagaimid ar an sainmhíniú ar shreabhadh.
Sreabhadh Is sraith sonraí é atá curtha in eagar de réir ama a thugann le fios go bhfuil athrú tagtha ar na sonraí. Anois, samhlaigh cé chomh áisiúil is atá sé cód a scríobh ina gcaithfidh tú roinnt imeachtaí a spreagadh i gcodanna éagsúla den chód le haghaidh gníomh amháin. Níl le déanamh againn ach liostáil leis an sruth agus inseoidh sé dúinn nuair a tharlaíonn athruithe. Agus is féidir leis an leabharlann RxJs é seo a dhéanamh.
RxJS leabharlann chun oibriú le cláir asincrónacha agus bunaithe ar imeachtaí ag baint úsáide as seichimh inbhraite. Soláthraíonn an leabharlann an príomhchineál Breathnaithe, roinnt cineálacha cúntóirí (Breathnóirí, Sceidealóirí, Ábhair(b) agus oibreoirí as oibriú le himeachtaí amhail bailiúcháin (léarscáil, scagaire, laghdú, gach agus cinn dá samhail ó JavaScript Array).
Tuigimid bunchoincheapa na leabharlainne seo.
Inbhraite, Breathnadóir, Léiritheoir
Is é inbhraite an chéad chineál bonn a bhreathnóimid air. Cuimsíonn an rang seo an phríomhchuid de chur i bhfeidhm RxJs. Tá baint aige le sruth inbhraite, ar féidir suibscríobh leis ag baint úsáide as an modh suibscríofa.
Cuireann inbhraite meicníocht chúnta i bhfeidhm chun nuashonruithe a chruthú, mar a thugtar air Observer. Tugtar foinse na luachanna do Bhreathnadóir Léiritheoir. Is féidir é a bheith ina eagar, ina iterator, ina soicéad gréasáin, imeacht de chineál éigin, etc. Mar sin is féidir linn a rá gur seoltóir idir an Táirgeoir agus an Breathnadóir é inbhraite.
Láimhseálann inbhraite trí chineál imeachtaí Observer:
seo chugainn - sonraí nua
earráid - earráid má tháinig deireadh leis an seicheamh mar gheall ar eisceacht. tugann an teagmhas seo le fios freisin deireadh an tseichimh.
iomlán - comhartha faoi dheireadh na seicheamh. Ciallaíonn sé seo nach mbeidh a thuilleadh sonraí nua ann
Feicfimid taispeántas:
Ag an tús déanfaimid na luachanna 1, 2, 3, agus tar éis 1 sec a phróiseáil. faighimid 4 agus cuirimid deireadh lenár snáithe.
Ag smaoineamh amach os ard
Agus ansin thuig mé go raibh sé níos suimiúla a insint ná a scríobh faoi. 😀
Síntiúis
Nuair a dhéanaimid liostáil le sruth, cruthaímid rang nua síntiús, a thugann an rogha dúinn díliostáil leis an modh díliostáil. Is féidir linn síntiúis a ghrúpáil freisin leis an modh cuir. Bhuel, tá sé loighciúil gur féidir linn snáitheanna a dhíghrúpáil ag baint úsáide as a bhaint. Glacann na modhanna cuir agus bain le síntiús difriúil mar ionchur. Ba mhaith liom a thabhairt faoi deara, nuair a dhéanaimid díliostáil, díliostáilimid ó gach síntiús linbh amhail is dá nglaoidís an modh díliostáil freisin. Lean ar aghaidh.
Cineálacha sruthanna
Te
FUAR
Cruthaítear táirgeoir lasmuigh den inbhraite
Cruthaítear táirgeoir taobh istigh inbhraite
Cuirtear sonraí ar aghaidh ag an am a chruthaítear an t-inbhraite
Cuirtear sonraí ar fáil tráth an tsíntiúis.
Teastaíonn níos mó loighce chun díliostáil
Críochnaíonn snáithe ar a chuid féin
Úsáideann caidreamh duine le go leor
Úsáideann caidreamh duine le duine
Tá an luach céanna ag gach síntiús
Tá síntiúis neamhspleách
Is féidir sonraí a chailleadh mura bhfuil síntiús ann
Atheisíonn sé gach sruthluach le haghaidh síntiús nua
Chun analaí a thabhairt, shamhlóinn sruth te cosúil le scannán i bpictiúrlann. Cén pointe ama a tháinig tú, ón nóiméad sin a thosaigh tú ag breathnú. Chuirfinn sruth fuar i gcomparáid le glao iontu siúd. tacaíocht. Éisteann glaoiteoir ar bith leis an meaisín freagartha ag taifeadadh ó thús deireadh, ach is féidir leat crochadh suas le díliostáil.
Ba mhaith liom a thabhairt faoi deara go bhfuil sruthanna te mar a thugtar orthu freisin (bhí mé tar éis teacht le sainmhíniú den sórt sin thar a bheith annamh agus i bpobail eachtracha amháin) - is sruth é seo a athraíonn ó shruth fuar go sruth te. Éiríonn an cheist - cá háit le húsáid)) Tabharfaidh mé sampla ó chleachtas.
Tá mé ag obair le Angular. Úsáideann sé rxjs go gníomhach. Chun sonraí a fháil chuig an bhfreastalaí, táim ag súil le sruth fuar agus úsáidim an sruth seo sa teimpléad ag baint úsáide as asyncPipe. Má úsáideann mé an píopa seo arís agus arís eile, ansin, ag filleadh ar an sainmhíniú ar shruth fuar, iarrfaidh gach píopa sonraí ón bhfreastalaí, rud atá aisteach a rá a laghad. Agus má thiontóidh mé sruth fuar go ceann te, tarlóidh an t-iarratas uair amháin.
Go ginearálta, tá sé deacair go leor do thosaitheoirí an cineál sreabhadh a thuiscint, ach tá sé tábhachtach.
Oibreoirí
return this.http.get(`${environment.apiUrl}/${this.apiUrl}/trade_companies`)
.pipe(
tap(({ data }: TradeCompanyList) => this.companies$$.next(cloneDeep(data))),
map(({ data }: TradeCompanyList) => data)
);
Tugann oibreoirí deis dúinn oibriú le sruthanna. Cuidíonn siad le rialú a dhéanamh ar na himeachtaí atá ag sreabhadh sa Inbhraite. Déanfaimid machnamh ar chúpla ceann de na cinn is mó tóir, agus is féidir tuilleadh faisnéise faoi na hoibreoirí a fháil ag na naisc i eolas úsáideach.
Oibreoirí-de
Let tús leis an oibreoir cúnta de. Cruthaíonn sé Inbhraite bunaithe ar luach simplí.
Oibreoirí-scagaire
Déanann an t-oibreoir scagaire, mar a thugann an t-ainm le tuiscint, an comhartha sruth a scagadh. Má fhilleann an t-oibreoir fíor, scipeann sé a thuilleadh.
Oibreoirí - a ghlacadh
ghlacadh - Glacann luach líon na n-astuithe, tar éis a chríochnaíonn an sruth.
Oibreoirí-debounceTime
debounceTime - caitheann sé luachanna astaithe a thagann laistigh den eatramh ama sonraithe idir sonraí aschuir - tar éis don eatramh ama a bheith caite, astaíonn sé an luach deiridh.
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)
);
Oibreoirí-takeWhile
Astaíonn luachanna go dtí go takeWhile returns false , ansin díliostáil ón snáithe.
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 )
);
Oibreoirí-combineLatest
Tá an t-oibreoir combineLatest beagán cosúil le promise.all. Nascann sé snáitheanna iolracha i gceann amháin. Tar éis do gach snáithe astaíocht amháin ar a laghad a dhéanamh, faighimid na luachanna is déanaí ó gach ceann acu i bhfoirm eagar. Ina theannta sin, tar éis aon astaíochtaí ó na sruthanna cumaisc, tabharfaidh sé luachanna nua.
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));
Oibreoirí-zip
Zip - fanann sé ar luach ó gach sruth agus cruthaíonn sé eagar bunaithe ar na luachanna seo. Mura dtagann an luach ó aon snáithe, ní bhunófar an grúpa.
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));
Oibreoirí - forkJoin
nascann forkJoin snáitheanna freisin, ach ní astaíonn sé luach ach amháin nuair a bhíonn na snáitheanna go léir críochnaithe.
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);
Oibreoirí-léarscáil
Athraíonn an t-oibreoir claochlaithe léarscáile an luach astaíochta go luach nua.
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)
);
Oibreoirí - roinnt, sconna
Ceadaíonn an t-oibreoir sconna duit fo-iarsmaí a dhéanamh, is é sin, aon ghníomhartha nach ndéanann difear don seicheamh.
Is féidir leis an oibreoir fóntais scaireanna sruth fuar a thiontú ina sruth te.
Déantar oibreoirí. Bogaimis ar aghaidh go dtí Ábhar.
Ag smaoineamh amach os ard
Agus ansin chuaigh mé ag ól tae. Tá mé tuirseach de na samplaí seo 😀
Teaghlaigh ábhair
Is sampla príomha de snáitheanna te é an teaghlach ábhair. Is cineál hibrideach iad na ranganna seo a fheidhmíonn mar bhreathnadóir agus inbhraite ag an am céanna. Ós rud é gur sruth te é an t-ábhar, ní mór é a dhíliostáil ó. Má labhairt linn faoi na príomh-mhodhanna, is iad seo:
seo chugainn - sonraí nua a thabhairt don sruth
earráid - earráid agus foirceannadh snáithe
iomlán - deireadh an tsnáithe
liostáil - liostáil le sruth
díliostáil - díliostáil ón snáithe
asInbhraite - chlaochlú ina bhreathnadóir
toPromise - transforms isteach gealltanas
Leithdháil 4 5 chineál ábhar.
Ag smaoineamh amach os ard
Dúirt mé 4 ar an sruth, ach d'éirigh sé amach chuir siad ceann amháin eile. Mar a théann an rá, beo agus foghlaim.
Ábhar Simplí new Subject()- an cineál ábhar is simplí. Cruthaithe gan paraiméadair. Gabhann na luachanna a tháinig ach amháin tar éis an síntiús.
Iompar Ábhar new BehaviorSubject( defaultData<T> ) - an cineál ábhar is coitianta i mo thuairim. Glacann an t-ionchur an luach réamhshocraithe. Sábhálann i gcónaí sonraí na heisiúna deiridh, a tharchuirtear nuair a shíntiúsaítear. Tá modh luacha úsáideach ag an aicme seo freisin a thugann luach reatha an tsrutha ar ais.
Ábhar Athimeartha new ReplaySubject(bufferSize?: number, windowTime?: number) - Roghnach, is féidir go dtógfaidh sé mar an chéad argóint méid an mhaoláin luachanna a stórálfaidh sé ann féin, agus an dara huair a dteastaíonn athruithe uainn.
ábhar sioncronaithe new AsyncSubject() - ní tharlaíonn aon rud nuair a shíníonn tú, agus ní thabharfar an luach ar ais ach amháin nuair a bheidh sé críochnaithe. Ní thabharfar ar ais ach luach deireanach an tsrutha.
WebSocketSubject new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig<T> | Observable<T>, destination?: Observer<T>) - Níl an doiciméadú ciúin faoi agus feicim féin é don chéad uair. Cé a fhios cad a dhéanann sé, scríobh, cuirfimid.
Phew. Bhuel, rinneamar machnamh ar gach rud a theastaigh uaim a insint inniu. Tá súil agam go raibh an t-eolas seo cabhrach. Is féidir leat an liosta litríochta leat féin a léamh sa chluaisín Faisnéise Úsáideacha.