2014-12-09 11 views
5

In Node.js, sollte ich Fehler für die Ablaufsteuerung verwenden, oder sollte ich sie eher als Ausnahmen verwenden?Best Practices für NodeJS: Fehler für die Ablaufsteuerung?

Ich schreibe einen Authentifizierungs-Controller und einige Komponententests in Sails.js, und derzeit überprüft meine Registrierungsmethode, ob ein Benutzer mit demselben Benutzernamen existiert. Wenn ein Benutzer bereits mit dem Benutzernamen vorhanden ist, ruft mein Modell Methode seine Rückruf Argumente mit einem neuen Error-Objekt, etwa so:

Modell:

exists: function (options, cb) { 
    User.findOne({ 
     where: { username: typeof options === 'Object' && options.username ? options.username : options }, 
    }).exec(function (err, user) { 
     if (err) return cb(err); 
     if (user) return cb(new Error("A user with that username already exists.")); 
     cb(null, !!user); 
    }); 
}, 

Controller:

User.exists(req.body.user.username, function (err, exists) { 
    if (err) { 
    console.log("error: ", err); 
    return res.status(409).json({ 
     message: err 
    });  
    } 

    User.create(req.user).then(function (data) { 
    res.status(201).json({ 
     user: data 
    }); 
    }); 
}); 

Ist das beste trainieren? Ich bin mir nicht sicher, ob Knotenkonventionen Fehler für Ausnahmefälle oder für die Ablaufsteuerung bevorzugen. Ich denke, ich sollte das umschreiben, aber ich möchte Konventionen kennen, bevor ich das tue. Ich glaube, ich habe einige Beispiele in Sails gesehen. Vielen Dank!

+0

Eine viel einfachere Weg ist, um Flagge der 'username' als einzigartig in der Modellschema und einfach die Verwendung Fehler Mongoose kehrt in Ihrem 'User.create()' Controller zurück, um mit einem 409 zu antworten. Dies ist ein optimistischerer Ansatz, denn wenn der Benutzer nicht existiert und eine gültige Anfrage vorliegt, treffen Sie die DB nicht zweimal ohne Grund . – srquinn

+0

@jibsales Das macht Sinn - aber was passiert dann, wenn es einen anderen Fehler gibt, der eine 500-Antwort erfordert?In Sprachen wie C# gibt es verschiedene Arten von Ausnahmen und Sie können nach diesem Typ suchen. Ich weiß, dass ich so etwas in Node machen könnte, wenn ich es möchte, aber ist das allgemein üblich? Die Entscheidung, die ich jetzt treffe, beeinflusst die Art, wie ich den Rest der Anwendung erstelle. Basierend auf Ihrem Kommentar scheint es so, als ob Knoten Fehler für die Flusskontrolle anstelle von Ausnahmesituationen verwendet. –

+0

Siehe meine Antwort unter – srquinn

Antwort

2

Die obige Antwort ist gut für Express, aber in Sails-Controller sollten Sie nicht anrufen next; Best Practice ist immer eine Antwort zurückzugeben. In den meisten Beispiel-Sails-Code sehen Sie nicht einmal next als Argument für eine Controller-Action-Funktion. Beachten Sie auch, dass Sails mit einigen default response methods direkt in das res Objekt, wie res.serverError und res.badRequest, sowie res.negotiate eingebaut ist, die versuchen werden, den Fehler basierend auf dem Statuscode an den entsprechenden Handler für Sie weiterzuleiten. So könnte Ihr Beispiel werden gezwickt als:

Modell:

exists: function (options, cb) { 
    User.findOne({ 
     where: { username: typeof options === 'Object' && options.username ? options.username : options }, 
    }).exec(function (err, user) { 
     // res.negotiate will default to a 500 server error 
     if (err) return cb(err); 
     // res.negotiate will just output the status code and error object 
     // as JSON for codes between 400 and 500, unless you 
     // provide a custom view as api/responses/badRequest.ejs 
     if (user) return cb({ 
      status: 409, 
      message: "A user with that username already exists." 
     }); 
     cb(null, !!user); 
    }); 
}, 

Controller:

User.exists(req.body.user.username, function (err, exists) { 
    // Let Sails handle those errors for you 
    if (err) {return res.negotiate(err);} 

    User.create(req.user).then(function (data) { 
    res.status(201).json({ 
     user: data 
    }); 
    }); 
}); 
+1

Diese Antwort richtig markiert - während die andere gut ist, ist dies Sails-spezifisch. Zum Schluss habe ich etwas Ähnliches gemacht, aber ich habe meine eigenen Fehlertypen erstellt, indem ich Error erweitert habe, und ich suche nach dem Typ, der Bluebird verspricht. –

2

Node (oder Javascript wirklich) können Fehler auf Ausnahmen auslösen, indem das Schlüsselwort throw:

if (something_went_wrong) { 
    throw new Error('Doh!'); 
} 

Sie können auch zusätzliche Parameter an das Objekt Standardfehler hinzufügen mehr semantische Bedeutung zu Ihren Fehlern in Ihrem Programm zu geben, . Wenn Sie das gesagt haben, möchten Sie keinen Fehler in Ihrem Routen-Handler ausgeben, da dies den Prozess und Ihren Server zum Absturz bringen würde.

Wenn Sie Routen-Handler in Sails verwenden (oder wirklich ausdrücken), sollten Sie die Art des Fehlers unbedingt prüfen und entsprechend auf den Client reagieren.

// -- Route handler 
app.get('/something', function (req, res, next) { 

    DB.create({ username: 'user' }, function (err, docs) { 

    if (err) { 

     // This checks to see if we have a unique error from MongoDB 
     // and send the appropriate response to the client 
     if (err.code === 11000 || error.code === 11001) { 
     return res.send(409); // or return res.json(409, {message: "User exists"}); 
     } 

     // Any other error type is assumed to be an internal error so we pass it 
     // down the chain to the error handler middleware 
     return next(err); 

    } 

    // This is a client error, not an internal error so we respond to the client 
    // with the appropriate client error type 
    if (docs.length === 0) return res.send(404); 

    if (user.notAuthorized) return res.send(403); 

    res.send('All Good'); 

    }); 

}); 

Beachten Sie, dass in dem Fall, dass die DB mit einem internen Fehler reagiert, wir die next() Funktion übergeben, die durch die Fehlerbehandlung Middleware in der Kette aufgenommen wird. Jede Middleware mit einer Arrigkeit von 4 ist als Fehlerbehandlungs-Middleware definiert. Sails hat wahrscheinlich einen Standard-Fehlerhandler, aber Sie können ihn wahrscheinlich auch überschreiben - Sie müssen die entsprechenden Dokumente für diese Informationen überprüfen, da ich das Steuerelement bevorzuge, das ich mit Express allein erhalte.

+0

Ich sehe. In diesem Fall kann ich Fehler für die Flusskontrolle verwenden, aber ich muss den Fehlercode oder Typ oder Namen überprüfen - was bedeutet, dass ich herausfinden muss, welche Arten von Fehlern Mongo oder Sails werfen könnten. Ich denke, ich mache Fortschritte bei dieser Quest. –

+0

@ jedd.ahyoung Fehler für die Ablaufsteuerung in dem Sinne, dass "err" -Werte bedeuten, dass ein Fehler aufgetreten ist. Ob Sie sie zur Ablaufsteuerung verwenden oder nicht, ist ein anderes Problem. Bedenken Sie auch, dass die Promistifier-Bibliotheken die Node-Konventionen zugunsten der normalen Semantik der Versprechungen verschwinden lassen. –

+0

@DaveNewton In der Tat. Sails enthält [Bluebird] (https://www.npmjs.org/package/bluebird) standardmäßig und ich habe darüber nachgedacht, es tatsächlich zu verwenden, da ich das Versprechen-Muster wirklich bevorzuge. Allerdings bietet Bluebird eine 'catch()' Methode für seine Fehler an, was (obwohl genial) immer noch bedeutet, dass ich die Namen und Typen der Fehler überprüfen muss. –