MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongoose gibt Daten aus dem withTransaction-Helfer heraus

Es sieht so aus, als gäbe es hier einige Verwirrung darüber, wie Promises auf mehreren Ebenen korrekt verwendet werden.

Callback und Promise werden falsch verwendet

Wenn die Funktion einen Rückruf akzeptieren soll, geben Sie kein Promise zurück. Wenn die Funktion ein Promise zurückgeben soll, verwenden Sie den vom Promise gegebenen Callback:

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")
            }
        });
    })

Sehen wir uns das genauer an:

return new Promise( (resolve, reject) => { Dadurch wird ein neues Promise erstellt, und das Promise gibt Ihnen zwei Rückrufe zur Verwendung. resolve ist ein Rückruf, um den Erfolg anzuzeigen. Sie übergeben ihm das Objekt, das Sie zurückgeben möchten. Beachten Sie, dass ich async entfernt habe Schlüsselwort (dazu später mehr).

Zum Beispiel:

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

(err, testData) => { Diese Funktion wird verwendet, um den Node-Stil cb(err, result) abzubilden zu den Rückrufen des Versprechens.

Try/Catch werden falsch verwendet.

Try/Catch kann nur für synchrone Anweisungen verwendet werden. Vergleichen wir einen synchronen Aufruf im Node-Stil (z. B. cb(err, result) ) asynchroner Rückruf, ein Promise und die Verwendung von await:

  • Synchron:
try {
    let a = doSomethingSync();
} catch(err) {
    handle(err);
}
  • Asynchron:
doSomethingAsync( (err, result) => {
    if (err) {
        handle(err);
    } else {
        let a = result;
    }
});
  • Versprechen:
doSomethingPromisified()
    .then( (result) => { 
        let a = result; 
    })
    .catch( (err) => {
        handle(err);
    });
  • Warte. Await kann mit jeder Funktion verwendet werden, die ein Promise zurückgibt, und Sie können den Code so behandeln, als wäre er synchron:
try {
    let a = await doSomethingPromisified();
} catch(err) {
    handle(err);
}

Zusätzliche Informationen

Promise.resolve()

Promise.resolve() erstellt ein neues Promise und löst dieses Promise mit einem undefinierten Wert auf. Dies ist eine Abkürzung für:

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

Das Callback-Äquivalent dazu wäre:

cb(err, undefined);

async

async geht mit await . Wenn Sie await verwenden in einer Funktion muss diese Funktion als async deklariert werden .

Genau wie await entpackt ein Versprechen (resolve in einen Wert und reject in eine Ausnahme), async Wraps Code in ein Versprechen. Ein return value -Anweisung wird in Promise.resolve(value) übersetzt , und eine ausgelöste Ausnahme throw e wird in Promise.reject(e) übersetzt .

Betrachten Sie den folgenden Code

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

Der obige Code entspricht dem:

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

Wenn Sie eine der obigen Funktionen ohne await aufrufen , erhalten Sie ein Versprechen zurück. Wenn Sie await In beiden Fällen erhalten Sie einen Wert zurück oder es wird eine Ausnahme ausgelöst.