MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Mongoose transmet les données hors de withTransaction helper

Il semble qu'il y ait une certaine confusion ici quant à la façon d'utiliser correctement Promesses, à plusieurs niveaux.

Le rappel et la promesse ne sont pas utilisés correctement

Si la fonction est censée accepter un rappel, ne renvoyez pas de Promise. Si la fonction est censée renvoyer une Promise, utilisez le callback donné par la 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")
            }
        });
    })

Regardons cela plus en détail :

return new Promise( (resolve, reject) => { Cela crée une nouvelle promesse, et la promesse vous donne deux rappels à utiliser. resolve est un rappel pour indiquer le succès. Vous lui passez l'objet que vous souhaitez rendre. Notez que j'ai supprimé le async mot-clé (plus à ce sujet plus tard).

Par exemple :

const a = new Promise( (resolve, reject) => resolve(5) );
a.then( (result) => result == 5 ); //true

(err, testData) => { Cette fonction est utilisée pour mapper le cb(err, result) de style Node aux rappels de la Promesse.

Try/catch sont utilisés de manière incorrecte.

Try/catch ne peut être utilisé que pour les instructions synchrones. Comparons un appel synchrone, un style Node (c'est-à-dire cb(err, result) ) rappel asynchrone, une promesse et en utilisant await :

  • Synchrone :
try {
    let a = doSomethingSync();
} catch(err) {
    handle(err);
}
  • Asynchrone :
doSomethingAsync( (err, result) => {
    if (err) {
        handle(err);
    } else {
        let a = result;
    }
});
  • Promesse :
doSomethingPromisified()
    .then( (result) => { 
        let a = result; 
    })
    .catch( (err) => {
        handle(err);
    });
  • Attendez. Await peut être utilisé avec n'importe quelle fonction qui renvoie une promesse et vous permet de gérer le code comme s'il était synchrone :
try {
    let a = await doSomethingPromisified();
} catch(err) {
    handle(err);
}

Informations supplémentaires

Promise.resolve()

Promise.resolve() crée une nouvelle promesse et résout cette promesse avec une valeur indéfinie. C'est un raccourci pour :

new Promise( (resolve, reject) => resolve(undefined) );

L'équivalent de rappel de ceci serait :

cb(err, undefined);

async

async va avec await . Si vous utilisez await dans une fonction, cette fonction doit être déclarée async .

Tout comme await déballe une promesse (resolve en une valeur, et reject dans une exception), async enveloppements code dans une promesse. Une return value l'instruction est traduite en Promise.resolve(value) , et une exception levée throw e est traduit en Promise.reject(e) .

Considérez le code suivant

async () => {
    return doSomethingSync();
}

Le code ci-dessus est équivalent à ceci :

() => {
    const p = new Promise(resolve, reject);
    try {
        const value = doSomethingSync();
        p.resolve(value);
    } catch(e) {
        p.reject(e);
    }
    return p;
}

Si vous appelez l'une des fonctions ci-dessus sans await , vous récupérerez une Promesse. Si vous await l'un ou l'autre, une valeur vous sera renvoyée ou une exception sera levée.