2016-04-03 4 views
2

Ich bin gerade mit Node/Express. Ich versuche eine einfache REST-API zu erstellen und ich frage mich, wie ich mit diesem Dilemma umgehen soll.Schreiben Middleware, die Agnostisch ist, wo es auf dem Stapel ist

Sagen, ich habe einen Controller eine Anforderung Aufnehmen (nach der Authentifizierung/andere Middleware-Komponenten ihre Sache getan haben), das ruft eine Modellfunktion, einige Daten zu erhalten, wie folgt aus:

module.exports = function (router) { 
    router.get('/api/resource1', a_model.get_all); 
}; 

Die Definition für das Modell wäre so etwas wie:

exports.get_all = function (req, res, next) { 
    db.any('select * from resource_table') 
    .then(function (data) { 
    res.status(200).json({ 
     status: 'success', 
     data: data, 
     message: 'Retrieved all the things.' 
    }); 
    }) 
    .catch(function (err) { 
    return next(err); 
    }); 
}; 

aber jetzt können sagen, dass ich einen anderen Controller haben, der muss mit den Daten einige andere Sachen zu tun, dass die Modell-Funktion aufrufen, sondern auch muss auch. Z.B.

module.exports = function (router) { 
    router.get('/api/resource2', a_model.get_all, do_stuff_with_data); 
}; 

Der aktuelle Stand der a_model.get_all wird nicht zulassen, do_stuff_with_data zu „Dinge tun“, weil es nie next() nennt.

Das Problem ist, dass, wenn ich es nur next() machen nennen, nachdem es res mutiert, erhalte ich eine Fehlermeldung, die besagt: Error: Can't set headers after they are sent wenn ich /api/resource1 getroffen.

Ich habe versucht, if (next) { next(); }, aber das funktioniert auch nicht, weil es immer die Fehler anfallende Middleware am unteren Rand des Stapels ist.

Eine mögliche Lösung wäre, am Ende meiner Middleware-Ketten eine Funktion zu platzieren, die einem NOP entspricht, so dass meine Module immer next() anrufen können, aber es muss einen besseren Weg geben, oder?

Antwort

3

Als Erstes können Sie nur einen Middleware-Handler haben, der die Antwort sendet. Also müssen Sie Ihren Code so gestalten, dass die Antwort auf die eingehende http-Anfrage an nur einer Stelle gesendet wird und Ihr Code sollte so organisiert werden, dass sehr klar ist, wie und wann das funktioniert.

Wenn Sie mehrere Middleware-Handler haben möchten, die zu einem Handler beitragen, können alle das eingehende req-Objekt untersuchen und alle Informationen zum Objekt res beitragen. Nachfolgende Handler können dann alle diese Informationen verwenden und darauf zugreifen.

Zum Beispiel könnte ein Middleware-Handler eine DB-Abfrage ausführen, verarbeitet die Abfrage dann als Informationen einige Ergebnisse in das res Objekt setzen, die dann bei der Bearbeitung dieser Anfrage an nachfolgenden Middleware-Handler zur Verfügung stehen werden.

Ein anderer Handler könnte die Daten weiter verarbeiten und jeweils an den nächsten weiterleiten, indem er next() aufruft.

Und dann schließlich könnte ein Handler die eigentliche Antwort senden und dieser Handler sollte nicht next() aufrufen, da es jetzt die Antwort gesendet hat, so dass die Antwort erfolgen muss.

Also, vielleicht müssen Sie nur Ihre Middleware trennen (die nur Daten für eine eventuelle Antwort vorbereitet) von dem Code, der tatsächlich die Antwort sendet. Ihre Middleware muss nur dann in der richtigen Reihenfolge sein, wenn bestimmte Middleware-Handler von der Verarbeitung von früheren Middleware-Handlern abhängig sind.

Dann muss Ihr Code, der tatsächlich die Ergebnisse der vorherigen Middleware-Verarbeitung verwendet, um die endgültige Antwort zu senden, nach der anderen Middleware sein. Normalerweise ist dies eine bestimmte Route und kein Middleware-Handler. Es gibt jedoch Fälle, in denen Middleware die endgültige Antwort senden könnte.

+0

Gah! Meine Verwirrung kam von einem Missverständnis dessen, was res.json() tat. Ich wusste nicht, dass es tatsächlich die Antwort gesendet hat. Das macht jetzt vollkommen Sinn, danke! (Ich war immer verwirrt darüber, was tatsächlich die Antwort gesendet hat. Lol. Ich dachte, es könnte eine Middleware gewesen sein, die für mich am Ende der Anrufkette angehängt ist.) – LukeP