MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Mangusto passa dados do withTransaction helper


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.