Node.js Promise Tutorial

⚡ Älykäs yhteenveto

Node.js:n promiset korvaavat syvälle sisäkkäiset takaisinkutsut palautetulla objektilla, joka laskee tilan kerran, joten asynkroninen tietokantatyöskentely tulkitaan litteäksi then-lauseiden ketjuksi anonyymien funktioiden pyramidin sijaan.

  • 🔘 Takaisinsoitto-ongelma: Sisäkkäiset takaisinkutsutoiminnot kasvavat pitkiksi ja vaikeiksi ylläpitää.
  • ☑️ Lupauksen perusteet: Promise palauttaa arvon ja toteutuu täsmälleen kerran.
  • ✅ Ketjutus: palauttaa sitten itse lupauksen, joten lisäykset suoritetaan järjestyksessä.
  • 🧪 Mukautetut lupaukset: q-kirjasto denodeify käärii kaikki takaisinkutsut.
  • 🛠️ Moderni muoto: async ja await kuluttavat lupauksia ilman takaisinkutsuja.
  • 📊 Virhesääntö: Käsittelemättömät hylkäykset ovat lopettaneet Node.js:n versiosta 15 lähtien.

Node.js Promise -opetusohjelma, jossa näytetään promiseihin ketjutetut takaisinkutsut

Aiemmissa opetusohjelmissa olisit nähnyt takaisinsoittotoimintoja, joita käytetään asynkronisissa tapahtumissa. Mutta joskus takaisinsoittotoiminnoista voi tulla painajainen, kun ne alkavat sisäkkäisiksi ja ohjelmasta tulee pitkä ja monimutkainen.

Mitä ovat lupaukset?

Ennen kuin aloitamme promiseilla, tarkastellaan ensin, mitä ovat "callback"-funktiot Node.jsOlemme nähneet näitä takaisinkutsufunktioita paljon edellisissä luvuissa, joten käydäänpä nopeasti läpi yksi niistä.

Alla oleva esimerkki näyttää koodinpätkän, jota käytetään yhteyden muodostamiseen a MongoDB tietokanta ja suorita päivitys yhdelle tietokannan tietueista.

Node.js-kutsutoiminto yhdistää kohteeseen MongoDB ja tietueen päivittäminen

  1. Yllä olevassa koodissa funktion osa (err,db) tunnetaan anonyymin tai takaisinsoittofunktion ilmoituksena. Kun MongoClient luo yhteyden MongoDB tietokanta, se palaa takaisinsoittotoimintoon, kun yhteys on valmis. Joten tietyssä mielessä yhteystoiminnot tapahtuvat taustalla, ja kun se on tehty, se kutsuu takaisinsoittotoimintomme. Muista, että tämä on yksi Node.js:n keskeisistä kohdista, jotta monet toiminnot voivat tapahtua samanaikaisesti eikä siten estä ketään käyttäjää suorittamasta toimintoa.
  2. Toinen koodilohko suoritetaan, kun takaisinsoittotoiminto todella kutsutaan. Takaisinsoittotoiminto päivittää vain yhden tietueen MongoDB tietokanta.

Mitä lupaus sitten on? No, lupaus on vain parannus Node.js:n takaisinsoittotoimintoihin. Kehityksen elinkaaren aikana saattaa esiintyä tapauksia, joissa useita takaisinsoittotoimintoja on sijoitettava yhteen. Tämä voi muuttua sotkuiseksi ja vaikeaksi ylläpitää tietyssä vaiheessa. Lyhyesti sanottuna lupaus on parannus takaisinsoittoihin, joilla pyritään lieventämään näitä ongelmia.

Lupauksen perussyntaksi on esitetty alla;

var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
  • "doSomethingAync" on mikä tahansa takaisinsoitto tai asynkroninen toiminto, joka suorittaa jonkinlaisen käsittelyn.
  • Tällä kertaa takaisinsoittoa määritettäessä palautetaan arvo, jota kutsutaan "lupaukseksi".
  • Kun lupaus palautetaan, sillä voi olla 2 lähtöä. Tämä määritellään "siis-lausekkeella". Joko toiminto voi olla onnistunut, mikä ilmaistaan ​​"onFulfilled"-parametrilla. Tai siinä voi olla virhe, joka on merkitty parametrilla "onRejected".

A lupaus istuu yhdessä kolmesta osavaltiosta ja asettuu kerran aloilleen:

Osavaltio Merkitys
Odotustilassa Työ ei ole päättynyt.
Fulfilled onFulfilled suoritetaan annetulla arvolla.
Hylätty onRejected suoritetaan virheellä.

Huomautus: Joten lupauksen avaintekijä on palautusarvo. Paluuarvon käsitettä ei ole käsitettä työskenneltäessä normaaleiden takaisinkutsujen kanssa Node.js:ssä. Palautusarvon ansiosta meillä on enemmän hallintaa siihen, kuinka takaisinsoittotoiminto voidaan määrittää.

Versiohuomautus: nämä esimerkit toimivat edelleen Node.js 24:llä, joka on Active LTS -versio vuonna 2026. Node.js 15:stä lähtien käsittelemätön hylkäys lopettaa prosessin varoituksen tulostamisen sijaan, joten sulje jokainen ketju .catch()-metodilla.

Seuraavassa aiheessa näemme esimerkin lupauksista ja siitä, kuinka ne hyötyvät takaisinsoittoista.

Takaisinsoitto lupauksiin

Katsotaanpa nyt esimerkkiä siitä, kuinka voimme käyttää "lupauksia" Node.js-sovelluksessa. Lupausten käyttäminen Node.js-sovelluksessa on ensin ladattava ja asennettava "lupaus"-moduuli.

Muokkaamme sitten koodiamme alla olevan mukaisesti, mikä päivittää Employee-kokoelman EmployeeName-tietueen promise-lupausten avulla.

Vaihe 1) Asentaminen NPM-moduulit

Jotta Promiseja voi käyttää Node.js-sovelluksessa, promise-moduuli on pakollinen. Asentaaksesi promise-moduulin, suorita alla oleva komento.

npm asennuslupaus

Vaihe 2) Muokkaa koodia niin, että se sisältää lupaukset

Editorin kuvakaappaus promise-moduulista, joka kirjoittaa uudelleen MongoDB päivitys

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';

MongoClient.connect(url)
    .then(function(err, db) {
        db.collection('Employee').updateOne({
            "EmployeeName": "Martin"
        }, {
            $set: {
                "EmployeeName": "Mohan"
            }
        });
    }); 

Code Selitys:

  1. Ensimmäinen osa on sisällyttää "lupaus"-moduuli, jonka avulla voimme käyttää lupaustoimintoa koodissamme.
  2. Voimme nyt liittää 'then'-funktion MongoClient.connect-toimintoomme. Tämä tarkoittaa siis sitä, että kun yhteys tietokantaan muodostetaan, meidän on suoritettava sen jälkeen määritetty koodinpätkä.
  3. Lopuksi määrittelemme koodinpätkämme, joka päivittää Martin-nimellä olevan työntekijän EmployeeName muotoon Mohan.

Huomautus:

Jos tarkistat nyt sisältösi MongoDB tietokanta, huomaat, että jos "Martin" EmployeeName -tietue on olemassa, se päivitetään muotoon "Mohan".

Tarkistaaksesi, että tiedot on lisätty oikein tietokantaan, sinun on suoritettava seuraavat komennot MongoDB

  1. käytä EmployeeDB:tä
  2. db.Employee.find({TyöntekijänNimi: “Mohan”})

Ensimmäinen lauseke varmistaa, että olet yhteydessä EmployeeDB-tietokantaan. Toinen lauseke etsii tietuetta, jonka työntekijän nimi on ”Mohan”.

Sisäkkäisten lupausten käsittely

Lupauksia määriteltäessä on huomioitava, että "siis"-menetelmä itsessään palauttaa lupauksen. Joten tietyssä mielessä lupaukset voivat olla sisäkkäisiä tai ketjutettuja toisiinsa.

Alla olevassa esimerkissä käytämme ketjutusta määrittääksemme 2 takaisinsoittofunktiota, jotka molemmat lisäävät tietueen MongoDB tietokanta.

(Huomautuksia: Ketjutus on käsite, jota käytetään yhdistämään menetelmien suorittaminen toisiinsa. Oletetaan, että sovelluksessasi on kaksi menetelmää nimeltä "methodA" ja "methodB". Ja logiikka oli sellainen, että 'methodB' pitäisi kutsua 'methodA':n jälkeen, sitten ketjutetaan suoritus siten, että 'methodB' kutsutaan suoraan 'methodA':n jälkeen.)

Tässä esimerkissä tärkein huomioitava asia on, että koodista tulee puhtaampi, luettavampi ja ylläpidettävä käyttämällä sisäkkäisiä lupauksia.

Ketjutetut sitten-lausekkeet, jotka lisäävät kaksi työntekijätietuetta MongoDB

var Promise = require('promise');
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost/EmployeeDB';
MongoClient.connect(url)

.then(function(db) {
    db.collection('Employee').insertOne({
        Employeeid: 4,
        EmployeeName: "NewEmployee"
    })

    .then(function(db1) {
        db1.collection('Employee').insertOne({
            Employeeid: 5,
            EmployeeName: "NewEmployee1"
        })
    })
});

Code Selitys:

  1. Määrittelemme nyt 2 "sitten" -lausetta, jotka suoritetaan peräkkäin. Ensimmäisessä lauseessa välitämme 'db'-parametrin, joka sisältää tietokantayhteytemme. Käytämme sitten "db"-yhteyden kokoelmaominaisuutta lisätäksemme tietueita "Työntekijä"-kokoelmaan. InsertOne-menetelmää käytetään varsinaisen asiakirjan lisäämiseen Employee-kokoelmaan.
  2. Käytämme sitten 2nd sitten lauseke myös toisen tietueen lisäämisestä tietokantaan.

Jos tarkistat nyt sisältösi MongoDB tietokannassa löydät 2 tietuetta lisättynä MongoDB tietokanta.

Nykyaikainen vastine: async ja await, jotka ovat olleet vakiona ES2017:stä lähtien, kuluttavat näitä lupauksia ilman takaisinkutsuja ja ovat suurelta osin korvanneet generaattoripohjainen vuonohjauskirjastot, kuten co, kun taas natiivi Promise-tuki tekee q:sta ja bluebirdistä tarpeettomia. Toinen lohko näyttää, että vastaanotetaan vain tietokantaa.

Mukautetun lupauksen luominen

Mukautettu lupaus voidaan luoda käyttämällä Node.js-moduulia nimeltä 'q'. 'q'-kirjasto on ladattava ja asennettava Node Package Managerin avulla. 'q'-kirjaston käytön jälkeen voidaan kutsua metodia "denodeify", joka muuttaa minkä tahansa funktion lupauksen palauttavaksi funktioksi.

Alla olevassa esimerkissä luomme yksinkertaisen funktion nimeltä "Lisää", joka lisää 2 numeroa. Muunnamme tämän funktion funktioksi, joka palauttaa lupauksen.

Kun tämä on tehty, näytämme viestin console.log-tiedostossa Lisää-toiminnon palauttaman lupauksen avulla.

Noudatetaan alla olevia ohjeita luodaksesi mukautetun funktiomme lupauksen palauttamiseksi.

Vaihe 1) NPM-moduulien asentaminen

Jotta 'q':ta voitaisiin käyttää Node.js-sovelluksessa, 'q'-moduuli vaaditaan. Asentaaksesi 'q'-moduulin, suorita alla oleva komento.

npm asennus q

Vaihe 2) Määritä seuraava koodi, jota käytetään mukautetun lupauksen luomiseen.

Wrapin rakentama räätälöity lupausping Yhteenlaskufunktio, jossa on q ja denodeify

Code Selitys:

  1. Ensimmäinen bitti on sisällyttää "q"-kirjasto käyttämällä vaadittua avainsanaa. Käyttämällä tätä kirjastoa voimme määrittää minkä tahansa toiminnon palauttamaan takaisinsoitto.
  2. Luomme funktiota nimeltä Add, joka lisää 2 muuttujissa a ja b määriteltyä numeroa. Näiden arvojen summa tallennetaan muuttujaan c.
  3. Sitten käytämme q-kirjastoa Add-funktiomme denodeifyyn (menetelmä, jota käytetään minkä tahansa funktion muuntamiseen promise-arvon palauttavaksi funktioksi) eli toisin sanoen muunnamme Add-funktiomme promise-arvon palauttavaksi funktioksi.
  4. Kutsumme nyt "Lisää"-toimintoamme ja pystymme saamaan palautuslupausarvon, koska suoritimme aiemman vaiheen denodeify Add-funktiosta.
  5. Avainsanaa 'then' käytetään määrittämään, että jos funktio suoritetaan onnistuneesti, console.log-tiedostossa näytetään merkkijono ”Yhteenlaskutoiminto suoritettu”.

Kun yllä oleva koodi suoritetaan, tulos "Lisäystoiminto suoritettu" näkyy console.logissa alla olevan kuvan mukaisesti.

Konsolin tulosteen yhteenlaskufunktio suoritettu mukautetusta lupauksesta

UKK

Node.js 15:stä lähtien prosessi päättyy nollasta poikkeavaan koodiin varoituksen sijaan. Liitä .catch() jokaiseen ketjuun tai rekisteröi prosessinkäsittelijä kirjautua sisään ja toipua.

.catch() vastaanottaa kaikki ketjun aiemmin heitetyt virheet, kuten try-lohkon. .finally() suoritetaan riippumatta siitä, miten ketju asettui, joten se sopii yhteyden sulkemiseen.

Promise.all epäonnistuu nopeasti, jos yksi syöte hylätään. allSettled ratkaisee ja raportoi aina jokaisen tuloksen. race hyväksyy ensimmäisen ratkaistun tuloksen. any tarvitsee yhden onnistumisen, muuten heittää AggregateError-virheen.

Molemmat käyttävät samaa promise-lupausta. await-tauot asynkronisen funktion sisällä, joten tulokset päätyvät tavallisiin muuttujiin ja virheet päätyvät try and catch -lohkoon.

Harvoin. Generator yield-funktiot ajoivat aikoinaan kirjastoja, kuten co, mutta async ja await kattavat kyseisen tehtävän natiivisti. Generatorsopivat edelleen laiskoille sekvensseille ja mukautetuille iteraattoreille.

util.promisify muuntaa callback-tyyppisen funktion suoraan, ja moduulit, kuten fs.promises, palauttavat jo promiseja. Molemmat korvaavat yllä olevan q-kirjaston.

Kyllä. Koneoppineet analysaattorit merkitsevät ketjuja ilman hylkäyskäsittelijää, odottavat sisäisiä silmukoita ja järjestyksestä riippuvia kirjoituksia ja luokittelevat sitten löydökset testit kulkemaan riskialttiimpia polkuja.

GitHub Copilot ja vastaavat agenttiavustajat kirjoittavat sisäkkäiset takaisinkutsut nopeasti uudelleen odotuskutsuiksi, mutta jokainen uudelleenkirjoitus on tarkistettava virhepolkujen ja reitti semantiikka muuttuu hiljaa.

Tiivistä tämä viesti seuraavasti: