Det verkar som att det finns en viss förvirring här om hur man korrekt använder Promises, på flera nivåer.
Callback och Promise används felaktigt
Om funktionen är tänkt att acceptera en återuppringning, returnera inte ett löfte. Om funktionen är tänkt att returnera ett löfte, använd återuppringningen från löftet:
const transactionSession = await mongoose.startSession()
await transactionSession.withTransaction( (tSession) => {
return new Promise( (resolve, reject) => {
//using Node-style callback
doSomethingAsync( (err, testData) => {
if(err) {
reject(err);
} else {
resolve(testData); //this is the equivalent of cb(null, "Any test data")
}
});
})
Låt oss titta på detta mer i detalj:
return new Promise( (resolve, reject) => {
Detta skapar ett nytt löfte, och löftet ger dig två återuppringningar att använda. resolve
är en återuppringning för att indikera framgång. Du skickar det objektet du vill lämna tillbaka. Observera att jag har tagit bort async
nyckelord (mer om detta senare).
Till exempel:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Denna funktion används för att mappa nodstilen cb(err, result)
till löftets återuppringningar.
Try/catch används felaktigt.
Try/catch kan endast användas för synkrona uttalanden. Låt oss jämföra ett synkront anrop, en nodstil (dvs. cb(err, result)
) asynkron återuppringning, ett löfte och användning av väntar:
- Synkron:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Asynk:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Lova:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Vänta. Await kan användas med vilken funktion som helst som returnerar ett löfte och låter dig hantera koden som om den vore synkron:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Ytterligare information
Promise.resolve()
Promise.resolve()
skapar ett nytt löfte och löser det löftet med ett odefinierat värde. Detta är en förkortning för:
new Promise( (resolve, reject) => resolve(undefined) );
Återuppringningsmotsvarigheten till detta skulle vara:
cb(err, undefined);
async
async
går med await
. Om du använder await
i en funktion måste den funktionen förklaras vara async
.
Precis som await
packar upp ett löfte (resolve
till ett värde och reject
till ett undantag), async
omslag kod till ett löfte. Ett return value
uttalande översätts till Promise.resolve(value)
, och ett slängt undantag throw e
översätts till Promise.reject(e)
.
Tänk på följande kod
async () => {
return doSomethingSync();
}
Koden ovan motsvarar detta:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Om du anropar någon av ovanstående funktioner utan att await
, du kommer att få tillbaka ett löfte. Om du await
någon av dem kommer du att få ett värde tillbaka, eller så kommer ett undantag att kastas.