#node.js #express #async-await #passport.js #asynchronous-javascript
Вопрос:
Все в моей стратегии passport-local, похоже, работает, за исключением обратного вызова verifycall, где оценка истинности validatesPassword
функции независимо возвращает значение true. Проблема может быть связана с тем, что validatesPassword
это асинхронная функция, и Promise {lt;pendinggt;}
вывод, когда функция работает не по порядку, не является ложным:
из файла паролей:
async function validatesPassword(passwordInput, dbHash) { let comparedInput = await bcrypt.compare(passwordInput, dbHash) //console.log("this is whats returned from compared Input " comparedInput) return comparedInput; }
Консоль.вход в validatesPassword
систему обычно печатается после вызова условного оператора в функции passport verifyCallback() в файле моего паспорта:
User.findOne(email) .then((dbResponse) =gt; { //console.log(dbResponse[0][0]); let user = dbResponse[0][0]; if (!user) { return done(null, false); } //no error, but also no user const isValid = validatesPassword(password, user.hash); //const isValid = false; if (isValid) { return done(null, user); } else { return done(null, false); } }) .catch((err) =gt; { console.log(err); done(err); }); } const strategy = new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, verifyCallback); passport.use(strategy) ...
Как видно выше, единственный способ, которым я могу вывести значение false из вышеупомянутого условия, — это явно установить isValid
значение false. Каков был бы наилучший способ заставить условное условие дождаться функции сравнения паролей ( validatesPassword
) и оценить ее возвращаемую логическую функцию? Должен ли я обещать validatesPassword
и добавить условное условие внутри (я пытался реализовать это самостоятельно, но безуспешно) этой функции и передать все это verifyCallback
функции в файле моего паспорта?
Ответ №1:
validatesPassword()
это async
функция. Как таковой, он ВСЕГДА возвращает обещание.
Итак, когда вы сделаете это:
const isValid = validatesPassword(password, user.hash); if (isValid) { // ... }
Это всегда будет правдой, потому isValid
что это обещание, так if (isValid)
что оно всегда пройдет. Вместо этого вы должны извлечь выгоду из обещания с .then()
помощью или await
, например:
const isValid = await validatesPassword(password, user.hash); if (isValid) { // ... }
Чтобы использовать await
его там, вам придется создать родительскую функцию async
.
Используя .then()
и комбинируя код, который вы показываете в своем вопросе, он может выглядеть следующим образом:
User.findOne(email).then((dbResponse) =gt; { let user = dbResponse[0][0]; if (!user) { return done(null, false); } return validatesPassword(password, user.hash).then(isValid =gt; { done(null, isValid ? user : false); }); }).catch((err) =gt; { console.log(err); done(err); });
Имейте в виду пару вещей об использовании async
и await
:
async
Функция всегда возвращает обещание.- Он возвращает это обещание, когда
async
функция попадает в первуюawait
очередь, и выполнение этойasync
функции приостанавливается в этот момент, но он немедленно возвращает обещание, и выполнение вызывающего кода, который получает это обещание, продолжается. - Некоторое время спустя, когда внутреннее обещание, которое вы используете
await
с помощью, разрешится, функция, которая ранее была приостановлена,await
возобновит выполнение. - Когда вы в конечном итоге получите возвращаемое значение в этой функции , например ваше
return comparedInput;
, это возвращаемое значение будет разрешенным значением обещания, которое ранее было возвращено изasync
функции. Таким образом, хотя это выглядит как синхронное возвращаемое значение, это не так. Поскольку функция естьasync
, возвращаемое значение становится разрешенным значением возвращаемого обещания. - Затем вызывающий абонент должен использовать либо
await
или.then()
, чтобы получить разрешенное значение из обещания.
Комментарии:
1. Я опубликовал свое решение, был бы признателен, если бы вы взглянули и сказали мне, что вы думаете, если сможете.
2. @DeltaFlyer — Я добавил новую версию к своему ответу.
Ответ №2:
от ответа jfriend00 у меня в голове завертелись колесики, хотя сначала я не был уверен, что понял. Я просмотрел использование условных выражений в обещаниях и условных выражениях, которые полагаются на обещания, и придумал это решение, в котором я .затем()’d validatesPassword
, а затем добавил условие внутри этого:
... User.findOne(email) .then((dbResponse) =gt; { //console.log(dbResponse[0][0]); let user = dbResponse[0][0]; if (!user) { return done(null, false); } //no error, but also no user console.log( ` here's the dbResponse Object: user: ${user.username}, password: ${user.hash}, ` ); validatesPassword(password, user.hash) .then((isValid) =gt; { if (isValid) { return done(null, user); } else { return done(null, false); } }) //const isValid = false; }) .catch((err) =gt; { console.log(err); done(err); }); } ...
Я не уверен, что это то, что предлагал jfriend00, но это решение, похоже, работает.
Комментарии:
1. Посмотрите, что я добавил к своему ответу. То, что у вас здесь есть, в основном в порядке. Одной вещи вам не хватает, если
validatesPassword()
вы отвергаете, вы не справляетесь с этим отказом. Я вернул это обещание, так что отказ будет пойман на более высоком уровне.catch()
. Разрешение отклонениям распространяться вверх может упростить обнаружение ошибок.