Parece que há alguma confusão aqui sobre como usar Promises corretamente, em vários níveis.
Retorno de chamada e promessa estão sendo usados incorretamente
Se a função deve aceitar um retorno de chamada, não retorne uma promessa. Se a função deve retornar um Promise, use o callback fornecido pelo Promise:
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")
}
});
})
Vejamos isso com mais detalhes:
return new Promise( (resolve, reject) => {
Isso cria um novo Promise, e o Promise está dando a você dois retornos de chamada para usar. resolve
é um retorno de chamada para indicar sucesso. Você passa o objeto que gostaria de devolver. Observe que eu removi o async
palavra-chave (mais sobre isso mais tarde). Por exemplo:
const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true
(err, testData) => {
Esta função é usada para mapear o estilo Node cb(err, result)
para os retornos de chamada da Promise. Try/catch está sendo usado incorretamente.
Try/catch só pode ser usado para instruções síncronas. Vamos comparar uma chamada síncrona, um estilo Node (ou seja,
cb(err, result)
) retorno de chamada assíncrono, uma promessa e usando await:- Síncrono:
try {
let a = doSomethingSync();
} catch(err) {
handle(err);
}
- Assíncrono:
doSomethingAsync( (err, result) => {
if (err) {
handle(err);
} else {
let a = result;
}
});
- Promessa:
doSomethingPromisified()
.then( (result) => {
let a = result;
})
.catch( (err) => {
handle(err);
});
- Aguarde. Await pode ser usado com qualquer função que retorne uma Promise e permite que você manipule o código como se fosse síncrono:
try {
let a = await doSomethingPromisified();
} catch(err) {
handle(err);
}
Informações adicionais
Promise.resolve()
Promise.resolve()
cria uma nova Promise e resolve essa Promise com um valor indefinido. Isso é uma abreviação para:new Promise( (resolve, reject) => resolve(undefined) );
O equivalente de retorno de chamada disso seria:
cb(err, undefined);
async
async
vai com await
. Se você estiver usando await
em uma função, essa função deve ser declarada como async
. Assim como
await
desembrulha uma promessa (resolve
em um valor e reject
em uma exceção), async
envoltórios código em uma promessa. Um return value
declaração é traduzida para Promise.resolve(value)
, e uma exceção lançada throw e
é traduzido para Promise.reject(e)
. Considere o seguinte código
async () => {
return doSomethingSync();
}
O código acima é equivalente a isso:
() => {
const p = new Promise(resolve, reject);
try {
const value = doSomethingSync();
p.resolve(value);
} catch(e) {
p.reject(e);
}
return p;
}
Se você chamar qualquer uma das funções acima sem
await
, você receberá de volta uma Promise. Se você await
qualquer um deles, você receberá um valor ou uma exceção será lançada.