MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Mongoose trasferisce i dati da withTransaction helper

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.