Sembra che ci sia un po' di confusione qui su come usare correttamente Promises, a diversi livelli.
Richiamata e Promessa vengono utilizzate in modo errato
Se la funzione dovrebbe accettare una richiamata, non restituire una promessa. Se si suppone che la funzione restituisca una promessa, utilizzare la richiamata fornita dalla promessa:
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")
}
});
})
Diamo un'occhiata più in dettaglio:
return new Promise( (resolve, reject) => {
Questo crea una nuova Promise e la Promise ti dà due callback da usare. resolve
è una richiamata per indicare il successo. Gli passi l'oggetto che desideri restituire. Nota che ho rimosso async
parola chiave (ne parleremo più avanti).
Ad esempio:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Questa funzione viene utilizzata per mappare lo stile del nodo cb(err, result)
alle richiamate della Promessa.
Try/catch vengono utilizzati in modo errato.
Try/catch può essere utilizzato solo per istruzioni sincrone. Confrontiamo una chiamata sincrona, uno stile Node (cioè cb(err, result)
) richiamata asincrona, una promessa e l'utilizzo di await:
- Sincrono:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Asincrono:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Promessa:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Aspetta. Await può essere utilizzato con qualsiasi funzione che restituisce una Promise e ti consente di gestire il codice come se fosse sincrono:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Informazioni aggiuntive
Promise.resolve()
Promise.resolve()
crea una nuova Promessa e la risolve con un valore indefinito. Questa è l'abbreviazione di:
new Promise( (resolve, reject) => resolve(undefined) );
L'equivalente di callback di questo sarebbe:
cb(err, undefined);
async
async
va con await
. Se stai usando await
in una funzione, quella funzione deve essere dichiarata async
.
Proprio come await
annulla una promessa (resolve
in un valore e reject
in un'eccezione), async
involucri codice in una promessa. Un return value
l'istruzione viene tradotta in Promise.resolve(value)
e un'eccezione generata throw e
viene tradotto in Promise.reject(e)
.
Considera il seguente codice
async () => {
return doSomethingSync();
}
Il codice sopra è equivalente a questo:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Se chiami una delle funzioni precedenti senza await
, riceverai indietro una Promessa. Se await
in entrambi i casi, ti verrà restituito un valore o verrà generata un'eccezione.