2017-07-11 2 views
0

Knoten 8.1.2, Ich habe eine Struktur, in der eine Datei eine andere Datei Funktion in einer Karte aufruft. In einem realen Beispiel würde ich Promise.all auf dem map verwenden, aber das ist nicht die Frage hier. Hier ist die Struktur:Behandlung von Fehlern (Ablehnungen) in async/erwarten innerhalb Array # Karte

A.js:

const { b } = require('./B') 

function expressStuff (req, res, next) { 
    things.map(thing => { 
    return b(thing) 
    })) 

    return res.status(200).json(...) 
} 

B.js:

// Thing -> Promise<Object> 
function b (thing) { 
    return ThingModel.update(...) // this returns a Promise but FAILS and throws an errror 
} 

module.exports = { b } 

OK. In der Funktion b versuche ich also asynchrone Daten (aus einer Datenbank) zu bekommen. Es schlägt fehl und wirft eine Unbegattete Promise Rejection.

Wie man damit umgehen?

Ich habe versucht, mehrere Lösungen:

A1.js:

const { b } = require('./B') 

function expressStuff (req, res, next) { 
    things.map(thing => { 
    try { 
     return b(thing) 
    } catch (err) { 
     return next(err) 
    } 
    })) 

    return res.status(200).json(...) 
} 

Aber das ist noch nicht erfasste.

A2.js:

const { b } = require('./B') 

function expressStuff (req, res, next) { 

    try { 
    things.map(thing => { 
     return b(thing) 
    })) 
    } catch (err) { 
    return next(err) 
    } 

    return res.status(200).json(...) 
} 

Noch nicht behandelte. Ich habe versucht, Promise.all mit, ich doppelt Try-Catch-Blöcke versucht (da ich derjenige innerhalb map gedacht sein könnte next von der zum map Ergebnis zurückkehren und nicht tatsächlich aus expressStuff Funktion. Immer noch nichts.

Das schließt ich das bekam Antwort wurde Umgang mit dem Fehler, aber dann würde Code nicht warten, bis es und beide res.status() geworfen werden und next funktionieren würde unter Rennbedingungen und cannot set headers after they are sent Fehler führt.

Alles, was ich will, ist für die Funktion tun b einen Fehler zu werfen aber fang es in der expressStuff, so dass ich benutzerdefinierteerneut auslösen kann 10 und übergeben Sie es an next. Es scheint wie Fehler von Datei B sprudelt nicht bis zum map, wo es heißt.

Wie mache ich das?

EDIT:

Die einzige Art, wie ich diese Ablehnung behandelt machen kann, ist versuchen Fang in der B.js. Aber wenn ich versuche, einen Fehler zu wiederholen/zurückzugeben - nichts. Fehler ist verschluckt. Wenn ich versuche, console.log es - es wird jedoch protokolliert werden.

DETAILS:

Dank deutliche Antwort, die ich meinen eigentlichen Code Refactoring und machte es perfekt zu arbeiten.

function expressStuff (res, req, next) { 
    try { 
    await Promise.all(things.map(async thing => { 
     if (ifSomething()) { 
     await b(thing) 
     } 
    })) 
    } catch (err) { 
    return next(new MyCustomError('My Custom Error Message')) 
    } 

    return res.status(200).json(...) 
} 

Antwort

1

Handhabung Ablehnungen mit try/catch funktioniert nur in async function s, wenn Sie await das Versprechen - die Sie noch nicht versucht haben.

könnten Sie tun entweder

async function expressStuff (req, res, next) { 
    var results; 
    try { 
    results = await Promise.all(things.map(b)); // throws when any of the promises reject 
    } catch (err) { 
    return next(err) // handle error 
    } 
    return res.status(200).json(...) 
} 

oder (wie Wait until all ES6 promises complete, even rejected promises)

function expressStuff (req, res, next) { 
    const resultPromises = things.map(async (thing) => { 
    try { 
     return await b(thing); // throws when the promise for this particular thing rejects 
    } catch (err) { 
     return defaultValue; // handle error - don't call `next` here 
    } 
    }); 
    … 
    return res.status(200).json(...) 
} 
+0

Ah, ja. Das ist ein toller Vorschlag! Aber das hat immer noch ein Problem mit 'Header kann nach dem Senden nicht gesetzt werden', da' return next (err) 'und' return res.status (200) 'beide versuchen auszuführen. Irgendeine Idee dazu? –

+0

@ TomaszGałkowski Sind Sie sicher, dass Sie beide Returns in der gleichen Funktion haben, wie in meiner Antwort? – Bergi

+0

Ja, positiv. Es ist eine asynchrone Funktion, die für eine Sache "wartet" und später diese Map macht. Nach der Map gibt es 200 zurück. Wenn ein Fehler in der Map auftritt, sollte er 'next' mit meinem benutzerdefinierten Fehler zurückgeben - und 422 senden. Was es jetzt zu tun versucht, dank Ihnen. Aber hier scheinen die Doppel-Header zu sein. –

Verwandte Themen