Zdá se, že je zde určitý zmatek, jak správně používat Promises, na několika úrovních.
Zpětné volání a Promise se používají nesprávně
Pokud má funkce přijmout zpětné volání, nevracejte Promise. Pokud má funkce vracet slib, použijte zpětné volání dané slibem:
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")
}
});
})
Podívejme se na to podrobněji:
return new Promise( (resolve, reject) => {
Tím se vytvoří nový Promise a Promise vám dává dvě zpětná volání, která můžete použít. resolve
je zpětné volání k označení úspěchu. Předáte mu předmět, který byste chtěli vrátit. Všimněte si, že jsem odstranil async
klíčové slovo (více o tom později).
Například:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Tato funkce se používá k mapování cb(err, result)
ve stylu uzlu na zpětná volání Promise.
Try/catch se používají nesprávně.
Try/catch lze použít pouze pro synchronní příkazy. Porovnejme synchronní volání ve stylu Node (tj. cb(err, result)
) asynchronní zpětné volání, Promise a pomocí wait:
- Synchronní:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Asynchronní:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Slib:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Počkejte. Await lze použít s jakoukoli funkcí, která vrací Promise a umožňuje vám zacházet s kódem, jako by byl synchronní:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Další informace
Promise.resolve()
Promise.resolve()
vytvoří nový slib a vyřeší tento slib s nedefinovanou hodnotou. Toto je zkratka pro:
new Promise( (resolve, reject) => resolve(undefined) );
Ekvivalent zpětného volání by byl:
cb(err, undefined);
async
async
jde s await
. Pokud používáte await
ve funkci musí být tato funkce deklarována jako async
.
Stejně jako await
rozbalí slib (resolve
do hodnoty a reject
do výjimky), async
zabalí kód do příslibu. return value
příkaz se přeloží do Promise.resolve(value)
a vyvolaná výjimka throw e
se přeloží do Promise.reject(e)
.
Zvažte následující kód
async () => {
return doSomethingSync();
}
Výše uvedený kód je ekvivalentní tomuto:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Pokud zavoláte některou z výše uvedených funkcí bez await
, dostanete zpět slib. Pokud await
buď vám bude vrácena hodnota nebo bude vyvolána výjimka.