Ohjelmointi

Asynkroninen JavaScript: Takaisinkutsut ja lupaukset selitetty

Asynkronisen koodin, eli koodin, joka ei toimi heti kuten verkkopyynnöt tai ajastimet, käsittely voi olla hankalaa. JavaScripti antaa meille kaksi tapaa käydä läpi asynkronista käyttäytymistä: soittopyynnöt ja lupaukset.

Soittopyynnöt olivat ainoa luonnostaan ​​tuettu tapa käsitellä asynkronikoodia vuoteen 2016 saakka, jolloin Lupaus esine esiteltiin kielelle. JavaScript-kehittäjät olivat kuitenkin toteuttaneet samanlaisia ​​toimintoja omina vuosina ennen lupausten saapumista paikalle. Katsotaanpa joitain soittopyyntöjen ja lupausten eroja ja katsotaan, miten käsittelemme useiden lupausten koordinointia.

Asynkroniset toiminnot, jotka käyttävät takaisinkutsuja, ottavat funktion parametriksi, jota kutsutaan, kun työ on valmis. Jos olet käyttänyt jotain setTimeout selaimessa, olet käyttänyt soittopyyntöjä.

// Voit määrittää soittopyynnön erikseen ...

anna myCallback = () => {

console.log ('Soitettu!');

};

setTimeout (myCallback, 3000);

//… mutta on myös tavallista nähdä takaisinsoittotiedot määriteltyinä rivin sisällä

setTimeout (() => {

console.log ('Soitettu!');

}, 3000);

Yleensä soittopyynnön vastaanottava funktio ottaa sen viimeiseksi argumentiksi. Näin ei ole edellä, joten teeskennetään, että on olemassa uusi toiminto nimeltä odota se on aivan kuten setTimeout mutta ottaa kaksi ensimmäistä argumenttia päinvastaisessa järjestyksessä:

// Käytämme uutta toimintoamme näin:

waitCallback (3000, () => {

console.log ('Soitettu!');

});

Sisäkkäiset soittopyynnöt ja tuomion pyramidi

Soittopyynnöt toimivat hyvin asynkronisen koodin käsittelyssä, mutta ne ovat hankalia, kun sinun on koordinoitava useita asynkronisia toimintoja. Esimerkiksi, jos halusimme odottaa kaksi sekuntia ja kirjata jotain, sitten odottaa kolme sekuntia ja kirjata jotain muuta, sitten odottaa neljä sekuntia ja kirjata jotain muuta, syntaksimme sisäkkäin.

// Käytämme uutta toimintoamme näin:

waitCallback (2000, () => {

console.log ('Ensimmäinen soittopyyntö!');

waitCallback (3000, () => {

console.log ('Toinen soittopyyntö!');

waitCallback (4000, () => {

console.log ('Kolmas soittopyyntö!');

    });

  });

});

Tämä saattaa tuntua triviaalilta esimerkiltä (ja onkin), mutta ei ole harvinaista, että teet useita verkkopyyntöjä peräkkäin edellisen pyynnön palautustulosten perusteella. Jos AJAX-kirjastosi käyttää takaisinsoittoja, näet yllä olevan rakenteen. Syvemmissä sisäkkäisissä esimerkeissä näet mitä kutsutaan tuomion pyramidiksi, joka saa nimensä pyramidin muodosta, joka on tehty rivien alussa olevalla sisennyksellä.

Kuten näette, koodimme sekoittuu rakenteellisesti ja sitä on vaikea lukea käsiteltäessä asynkronisia toimintoja, joiden on tapahduttava peräkkäin. Mutta se tulee vielä hankalammaksi. Kuvittele, haluaisimmeko aloittaa kolme tai neljä verkkopyyntöä ja suorittaa jonkin tehtävän vasta, kun kaikki ovat palanneet. Kannustan sinua yrittämään sen, jos et ole vielä törmännyt haasteeseen.

Helpompaa asynkronointia lupausten kanssa

Lupaukset tarjoavat joustavamman sovellusliittymän asynkronisten tehtävien käsittelemiseksi. Se vaatii funktion kirjoittamisen siten, että se palauttaa a Lupaus objekti, jolla on joitain vakio-ominaisuuksia myöhemmän käyttäytymisen käsittelemiseksi ja useiden lupausten koordinoimiseksi. Jos meidän waitCallback toiminto oli Lupaus-perusteisesti, se vie vain yhden argumentin, joka on millisekunnit odottamista. Kaikki myöhemmät toiminnot olisivat ketjutettu lupauksesta. Ensimmäinen esimerkkimme näyttäisi tältä:

anna myHandler = () => {

console.log (’Soitettu!’);

};

waitPromise (3000) .Sitten (myHandler);

Yllä olevassa esimerkissä odota lupaus (3000) palauttaa a Lupaus objekti, jolla on joitain menetelmiä, joita voimme käyttää, kuten sitten. Jos haluaisimme suorittaa useita asynkronisia toimintoja peräkkäin, voisimme välttää tuomion pyramidin lupauksilla. Koodi, joka on kirjoitettu tukemaan uutta lupaustamme, näyttäisi tältä:

// Riippumatta siitä, kuinka monta peräkkäistä asynkronointitehtävää meillä on, emme koskaan tee pyramidia.

waitPromise (2000)

. sitten (() => {

console.log ('Ensimmäinen soittopyyntö!');

paluu waitPromise (3000);

  })

. sitten (() => {

console.log ('Toinen soittopyyntö!');

paluu waitPromise (4000);

  })

. sitten (() => {

console.log ('Toinen soittopyyntö!');

paluu waitPromise (4000);

  });

Vielä parempaa, jos meidän on koordinoitava asynkronisia tehtäviä, jotka tukevat Promisesia, voimme käyttää kaikki, joka on staattinen menetelmä Lupaus esine, joka ottaa useita lupauksia ja yhdistää ne yhdeksi. Se näyttäisi tältä:

Promise.all ([

waitPromise (2000),

waitPromise (3000),

odota lupaus (4000)

sitten (() => console.log ('Kaikki on tehty!'));

Ensi viikolla selvitämme tarkemmin, miten lupaukset toimivat ja miten niitä voidaan käyttää idiomaattisesti. Jos opit vain JavaScriptiä tai olet kiinnostunut testaamaan tietosi, yritä waitCallback tai yritä saavuttaa vastaava Promise.all takaisinsoittojen kanssa.

Kuten aina, ota minuun yhteyttä Twitterissä kommenteilla tai kysymyksillä.