Ich füge eine sehr einfache Login-Methode zu einem Bookshelf-Benutzermodell in einer ExpressJS-App, aber ich kann nicht die Fehler von der abgelehnten Versprechen, dass die Login-Funktion im Benutzermodell zurückgibt . Ich schaue auf Bookshelf Beispiel Beispiel Login in der Dokumentation unter http://bookshelfjs.org/#Model-static-extend, aber dieses Beispiel verwendet Bluebird, während ich versuche, das gleiche mit den integrierten ES6 verspricht.Abfangen von Fehlern mit ES6 Versprechen und BookshelfJS
Mein Login-Methode im Benutzermodell:
userModel.js
function login(email, password) {
return new Promise((resolve, reject) => {
User.where('email', email)
.fetch({ require: true })
.then(user => {
bcrypt.compare(password, user.get('password'), (err, matched) => {
if (!matched) return reject(new Error('Password didn\'t match!'));
resolve(user);
});
});
});
Die Aktion-Controller, der Login implementiert und ruft User.login
aus dem Bücherregal User
Modell:
usersAuthController. js
function logUserIn(req, res) {
new User().login(req.body.email, req.body.password)
.then(user => res.json({ message: 'Login succeeded!' }))
.catch(User.NotFoundError,() => res.status(404).json({ error: 'User not found!' }) // catch #1
.catch(err => res.status(401).json({ err: err.message })); // catch #2
}
Meine Absicht ist, dass login()
eine abgelehnte Versprechen zurückgeben kann, wenn Bookshelf User.fetch
Methode den Benutzer mit der angegebenen E-Mail nicht finden kann. In diesem Fall sollte die Zeile .catch(User.NotFoundError ...)
(catch # 1) es fangen und eine 404 zurückgeben. Ich beabsichtige auch login()
, eine zurückgewiesene Zusage zurückzugeben, wenn bcrypt
feststellt, dass das an login()
übergebene Kennwort nicht mit dem Kennwort des Benutzers übereinstimmt "catch-all" (Fang # 2) unter der User.NotFoundError
catch-Anweisung zurückgeben sollte ein 401.
Wenn ich in dem falschen Passwort setzen, die logUserIn()
Controller-Aktion in dem obigen Code geht { error: "Cannot set property 'message' of undefined" }
# 2 mit der Fehlermeldung zu fangen anstelle der Nachricht 'Password didn't match!'
Nachricht, die ich in login()
abgelehnt habe. Wenn ich eine nicht vorhandene E-Mail einfüge, wird die Antwort nie gesendet und der Fehler Unhandled rejection CustomError: EmptyResponse
wird in der Konsole ausgelöst. Nur gültige Eingabe funktioniert.
Ein Versuch zu beheben: fangen User.NotFoundError
direkt im Modell statt.
Ich zog Fang # 1 zum Modell Benutzer, so dass die Login-Methode wie jetzt aussieht:
userModel.js
function login(email, password) {
return new Promise((resolve, reject) => {
User.where('email', email)
.fetch({ require: true })
.then(user => {
bcrypt.compare(password, user.get('password'), (err, matched) => {
if (!matched) return reject(new Error('Password didn\'t match!'));
resolve(user);
});
})
.catch(User.NotFoundError,() => reject({ error: 'User not found!' }));
});
Auf diese Weise kann ich beiden Fehler (falsches Passwort fangen und nicht existierende Email) korrekt, aber so kann ich den Statuscode im Controller nicht angeben. Wenn der Benutzer mit der angegebenen E-Mail nicht gefunden werden konnte, sollte er eine 404 zurückgeben, aber wenn das Passwort falsch war, sollte es eine 401 zurückgeben, aber beide Fehler gehen an die Catch-All (Catch # 2) in der Controller-Aktion (die immer eine 401 zurückgibt).
Um dieses Problem, in dem User
Modell lösen konnte ich .catch(User.NotFoundError,() => reject({ name: 'NotFoundError', message: 'User not found!' }))
und in der Controller-Aktion tun kann ich überprüfen, welche Art von Fehlern, die ich bin mit const statusCode = err.name === 'NotFoundError' ? 404 : 401
bekommen, aber das scheint wirklich chaotisch und trifft nicht den Punkt diese .catch
Aussagen des Habens .
Gibt es eine Möglichkeit, die User.NotFoundError
von der Login-Methode des Modells und alle anderen Fehler alle in logInUser
zu fangen? Warum funktioniert das Setup nicht zuerst, das mit beiden catch
Anweisungen in usersAuthController.js, und was haben die Cannot set property 'message' of undefined'
und CustomError: EmptyResponse
Fehler bedeutet (hat es etwas damit zu tun, Bookshelf Bluebird Versprechungen gegenüber den eingebauten ES6 Versprechen zu vermischen)? Was ist der beste Weg, damit umzugehen?
Vermeiden Sie die [ 'Promise' Konstruktor Antipattern] (http://stackoverflow.com/q/23803743/1048572)! Sie sollten nur 'bcrypt.compare' in dieser' login' Funktion promiden. – Bergi