Parece que hay cierta confusión aquí sobre cómo usar Promesas correctamente, en varios niveles.
Devolución de llamada y Promesa se utilizan incorrectamente
Si se supone que la función debe aceptar una devolución de llamada, no devuelva una Promesa. Si se supone que la función devolverá una Promesa, use la devolución de llamada dada por la Promesa:
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")
}
});
})
Veamos esto con más detalle:
return new Promise( (resolve, reject) => {
Esto crea una nueva Promesa, y la Promesa te da dos devoluciones de llamada para usar. resolve
es una devolución de llamada para indicar el éxito. Le pasas el objeto que te gustaría devolver. Tenga en cuenta que he eliminado el async
palabra clave (más sobre esto más adelante).
Por ejemplo:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Esta función se usa para mapear el estilo de nodo cb(err, result)
a las devoluciones de llamadas de Promise.
Intentar/atrapar se está utilizando incorrectamente.
Try/catch solo se puede usar para declaraciones síncronas. Comparemos una llamada síncrona, un estilo de nodo (es decir, cb(err, result)
) devolución de llamada asíncrona, una Promesa y usar await:
- Sincrónico:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Asíncrono:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Promesa:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Espera. Await se puede usar con cualquier función que devuelva una Promesa y le permite manejar el código como si fuera sincrónico:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Información adicional
Promise.resolve()
Promise.resolve()
crea una nueva Promesa y resuelve esa Promesa con un valor indefinido. Esta es la abreviatura de:
new Promise( (resolve, reject) => resolve(undefined) );
El equivalente de devolución de llamada de esto sería:
cb(err, undefined);
async
async
va con await
. Si está utilizando await
en una función, esa función debe declararse como async
.
Así como await
desenvuelve una Promesa (resolve
en un valor, y reject
en una excepción), async
envolturas código en una promesa. Un return value
la declaración se traduce a Promise.resolve(value)
, y una excepción lanzada throw e
se traduce a Promise.reject(e)
.
Considere el siguiente código
async () => {
return doSomethingSync();
}
El código anterior es equivalente a esto:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Si llama a cualquiera de las funciones anteriores sin await
, obtendrás una Promesa. Si await
cualquiera de ellos, se le devolverá un valor o se lanzará una excepción.