Node.js Promise-opplæring

⚡ Smart oppsummering

Løfter i Node.js erstatter dypt nestede tilbakeringinger med et returnert objekt som utlignes én gang, slik at asynkront databasearbeid leses som en flat kjede av «then»-klausuler i stedet for en pyramide av anonyme funksjoner.

  • 🔘 Problem med tilbakeringing: Nestede tilbakeringinger blir lange og vanskelige å vedlikeholde.
  • ☑️ Grunnleggende løfter: Et løfte returnerer en verdi og utbetales nøyaktig én gang.
  • Kjetting: returnerer deretter selv et løfte, slik at innsettinger kjøres i rekkefølge.
  • 🧪 Tilpassede løfter: Q-biblioteket denodeify pakker inn alle tilbakekall.
  • 🛠️ Moderne form: async og await consume-løfter uten deretter tilbakeringinger.
  • 📊 Feilregel: Ubehandlede avvisninger avslutter Node.js siden versjon 15.

Node.js Promise-veiledning som viser tilbakeringinger lenket til løfter

I tidligere opplæringsprogrammer ville du ha sett tilbakeringingsfunksjoner som brukes for asynkrone hendelser. Men noen ganger kan tilbakeringingsfunksjoner bli et mareritt når de begynner å bli nestet, og programmet begynner å bli langt og komplekst.

Hva er løfter?

Før vi begynner med løfter, la oss først se på hva «tilbakeringingsfunksjoner» er i node.jsVi har sett disse tilbakeringingsfunksjonene mye i de foregående kapitlene, så la oss raskt gå gjennom en av dem.

Eksemplet nedenfor viser en kodebit som brukes til å koble til en MongoDB database og utføre en oppdateringsoperasjon på en av postene i databasen.

Node.js tilbakeringingsfunksjon kobler til MongoDB og oppdaterer en post

  1. I koden ovenfor er delen av funksjonen (err,db) kjent som erklæringen om en anonym funksjon eller tilbakeringingsfunksjon. Når MongoClient oppretter en forbindelse til MongoDB databasen, vil den gå tilbake til tilbakeringingsfunksjonen når tilkoblingsoperasjonen er fullført. Så på en måte skjer tilkoblingsoperasjonene i bakgrunnen, og når det er gjort, kaller det tilbakeringingsfunksjonen vår. Husk at dette er et av nøkkelpunktene til Node.js for å tillate mange operasjoner å skje samtidig og dermed ikke blokkere noen bruker fra å utføre en operasjon.
  2. Den andre kodeblokken er det som blir utført når tilbakeringingsfunksjonen faktisk kalles. Tilbakeringingsfunksjonen oppdaterer bare én post i vår MongoDB database.

Så hva er et løfte da? Vel, et løfte er bare en forbedring av tilbakeringingsfunksjoner i Node.js. I løpet av utviklingslivssyklusen kan det være et tilfelle hvor du må legge flere tilbakeringingsfunksjoner sammen. Dette kan bli litt rotete og vanskelig å vedlikeholde på et bestemt tidspunkt. Kort sagt, et løfte er en forbedring av tilbakeringinger som ser ut til å lindre disse problemene.

Den grunnleggende syntaksen til et løfte er vist nedenfor;

var promise = doSomethingAync()
promise.then(onFulfilled, onRejected)
  • "doSomethingAync" er enhver tilbakeringing eller asynkron funksjon som utfører en form for behandling.
  • Denne gangen, når du definerer tilbakeringingen, er det en verdi som returneres kalt et "løfte."
  • Når et løfte returneres, kan det ha 2 utganger. Dette er definert av 'då-klausulen'. Enten kan operasjonen være en suksess som er angitt med parameteren 'onFulfilled'. Eller det kan ha en feil som er angitt med parameteren 'onRejected'.

A løfte sitter i en av tre stater og bosetter seg én gang:

Tilstand Betydning
Venter Arbeidet er ikke ferdig.
Oppfylt onFulfilled kjører med verdien.
Avvist onRejected kjører med feilen.

OBS: Så nøkkelaspektet ved et løfte er returverdien. Det er ikke noe konsept for en returverdi når du arbeider med normale tilbakeringinger i Node.js. På grunn av returverdien har vi mer kontroll over hvordan tilbakeringingsfunksjonen kan defineres.

Versjonsmerknad: Disse eksemplene kjører fortsatt på Node.js 24, den aktive LTS-linjen i 2026. Siden Node.js 15 og ubehandlet avvisning avslutter prosessen i stedet for å skrive ut en advarsel, så lukk hver kjede med .catch().

I neste emne vil vi se et eksempel på løfter og hvordan de drar nytte av tilbakeringinger.

Tilbakeringing til løfter

La oss nå se på et eksempel på hvordan vi kan bruke "løfter" fra en Node.js-applikasjon. For å bruke løfter i en Node.js-applikasjon, må 'løfte'-modulen først lastes ned og installeres.

Vi vil deretter endre koden vår som vist nedenfor, som oppdaterer et EmployeeName i «Employee»-samlingen ved hjelp av løfter.

Trinn 1) Installere NPM-moduler

For å bruke Promises fra et Node.js-program, kreves promise-modulen. For å installere promise-modulen, kjør kommandoen nedenfor.

npm installeringsløfte

Trinn 2) Endre koden for å inkludere løfter

Redaktørens skjermbilde av løftemodulen som omskriver MongoDB Oppdater

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 Forklaring:

  1. Den første delen er å inkludere 'løfte'-modulen som vil tillate oss å bruke løftefunksjonaliteten i koden vår.
  2. Vi kan nå legge til 'da'-funksjonen til vår MongoClient.connect-funksjon. Så det dette gjør er at når tilkoblingen er opprettet til databasen, må vi kjøre kodebiten definert deretter.
  3. Til slutt definerer vi vår kodebit som gjør jobben med å oppdatere EmployeeName til den ansatte med navnet "Martin" til "Mohan".

OBS:

Hvis du nå sjekker innholdet i din MongoDB database, vil du finne at hvis en post med EmployeeName av "Martin" eksisterer, vil den bli oppdatert til "Mohan."

For å kontrollere at dataene er satt inn riktig i databasen, må du utføre følgende kommandoer i MongoDB

  1. bruk EmployeeDB
  2. db.Ansatt.finn({Ansattnavn: “Mohan”})

Den første setningen sikrer at du er koblet til EmployeeDB-databasen. Den andre setningen søker etter posten som har ansattnavnet «Mohan».

Håndtering av nestede løfter

Når du definerer løfter, må det bemerkes at "da"-metoden i seg selv returnerer et løfte. Så på en måte kan løfter være nestet eller lenket til hverandre.

I eksemplet nedenfor bruker vi kjeding til å definere 2 tilbakeringingsfunksjoner, som begge setter inn en post i MongoDB database.

(Merknader: Kjeding er et konsept som brukes for å koble utførelse av metoder til hverandre. Tenk deg at søknaden din hadde to metoder kalt 'metodeA' og 'metodeB'. Og logikken var slik at 'metodeB' skulle kalles etter 'metodeA', så ville du lenke utførelsen på en slik måte at 'metodeB' blir kalt direkte etter 'metodeA.')

Det viktigste å merke seg i dette eksemplet er at koden blir renere, lesbar og vedlikeholdbar ved å bruke nestede løfter.

Kjedede deretter-klausuler som setter inn to ansattposter i 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 Forklaring:

  1. Vi definerer nå 2 "da"-klausuler som blir utført etter hverandre. I den første klausulen sender vi 'db'-parameteren som inneholder databasetilkoblingen vår. Vi bruker da samlingsegenskapen til 'db'-forbindelsen for å sette inn poster i 'Ansatt'-samlingen. 'insertOne'-metoden brukes til å sette inn selve dokumentet i ansattsamlingen.
  2. Vi bruker da 2nd deretter klausul også for å sette inn en annen post i databasen.

Hvis du nå sjekker innholdet i din MongoDB databasen, finner du de to postene som er satt inn i MongoDB database.

Moderne ekvivalent: async og await, standard siden ES2017, forbruker disse løftene uten deretter tilbakeringinger og har i stor grad erstattet generatorbasert flytkontrollbiblioteker som co, mens innebygd Promise-støtte gjør q og bluebird overflødige. Den andre blokken viser at de da bare mottar db.

Opprette et tilpasset løfte

Et tilpasset løfte kan opprettes ved å bruke en Node.js-modul kalt «q». «Q»-biblioteket må lastes ned og installeres ved hjelp av Node Package Manager. Etter bruk av «q»-biblioteket kan metoden «denodeify» kalles, noe som vil føre til at en hvilken som helst funksjon blir en funksjon som returnerer et løfte.

I eksemplet nedenfor vil vi lage en enkel funksjon kalt "Legg til" som vil legge til 2 tall. Vi vil konvertere denne funksjonen til en funksjon for å returnere et løfte.

Når det er gjort, vil vi bruke løftet som returneres av Add-funksjonen for å vise en melding i console.log.

La oss følge trinnene nedenfor for å lage vår egendefinerte funksjon for å returnere et løfte.

Trinn 1) Installere NPM-modulene

For å bruke 'q' fra et Node.js-program, kreves 'q'-modulen. For å installere 'q'-modulen, kjør kommandoen nedenfor.

npm installer q

Trinn 2) Definer følgende kode som skal brukes til å lage det tilpassede løftet.

Tilpasset løfte bygget av wrapping en addisjonsfunksjon med q denodeify

Code Forklaring:

  1. Den første biten er å inkludere 'q'-biblioteket ved å bruke nøkkelordet require. Ved å bruke dette biblioteket vil vi kunne definere hvilken som helst funksjon for å returnere en tilbakeringing.
  2. Vi lager en funksjon kalt Add som vil legge til 2 tall definert i variablene a og b. Summen av disse verdiene vil bli lagret i variabel c.
  3. Deretter bruker vi q-biblioteket til å avkode (metoden som brukes til å konvertere en hvilken som helst funksjon til en funksjon som returnerer et løfte) Add-funksjonen vår, eller med andre ord, konvertere Add-funksjonen vår til en funksjon som returnerer et løfte.
  4. Vi kaller nå "Legg til"-funksjonen vår og er i stand til å få en returløfteverdi på grunn av det forrige trinnet vi utførte med å denodeifisere Add-funksjonen.
  5. Nøkkelordet «then» brukes til å spesifisere at hvis funksjonen utføres uten problemer, skal strengen «Addisjonsfunksjon fullført» vises i console.log.

Når koden ovenfor kjøres, vil utdata "Addition function completed" vises i console.log som vist nedenfor.

Utskrift av konsollutgang Tilleggsfunksjon fullført fra det tilpassede løftet

Spørsmål og svar

Siden Node.js 15 avsluttes prosessen med en kode som ikke er null i stedet for en advarsel. Legg ved .catch() til hver kjede, eller registrer en prosessbehandler å logge og gjenopprette.

.catch() mottar alle feil som oppstår tidligere i kjeden, som en try-blokk. .finally() kjører uansett hvilken vei kjeden har nådd, så den passer til å lukke en forbindelse.

Promise.all mislykkes raskt hvis ett input-resultat avvises. allSettled løser og rapporterer alltid alle utfall. race tar i bruk det første avgjorte resultatet. any trenger én suksess, ellers kaster AggregateError.

Begge bruker det samme løftet. await-pauser inne i en asynkron funksjon, slik at resultatene lander i vanlige variabler og feilene når en try and catch-blokk.

Sjelden. Generator funksjoner med yield drev en gang biblioteker som co, men async og await dekker den jobben direkte. Generators passer fortsatt til late sekvenser og tilpassede iteratorer.

util.promisify konverterer en callback-lignende funksjon direkte, og moduler som fs.promises leverer allerede tilbake løfter. Begge erstatter q-biblioteket vist ovenfor.

Ja. Maskinlærte analysatorer flagger kjeder uten avvisningsbehandler, venter på interne løkker og rekkefølgeavhengige skrivinger, og rangerer deretter funnene slik at tester gå de risikable stiene.

GitHub Copilot og lignende agentassistenter omskriver nestede tilbakeringinger raskt som ventende anrop, men hver omskriving må gjennomgås fordi feilstier og rute semantikk endres stille.

Oppsummer dette innlegget med: