首页 > 解决方案 > Express.js 使用 await 和护照

问题描述

我正在尝试将 mySQL 添加到 passport.js 以对 express.js 中的用户进行身份验证,但似乎无法等待工作。服务器.js:

initializePassport(
  passport,
  function(email) {
    pool.getConnection(function(err, connection) {
      if (err) throw err;
      console.log("Connected!");
      pool.query("SELECT * FROM users WHERE email = ?", email, function (err, result) {
        if (err) throw err;
        return result[0];

        connection.release();
      });
    });
  },
)

护照配置

function initialize(passport, getUserByEmail) {
  const authenticateUser = async (email, password, done) => {
    try {
      const user = await getUserByEmail(email);
      console.log(user)
    } catch (e) {
      return done(e)
    }

现在它只是为用户打印 undefined,然后打印 Connected。我不确定为什么 await 用户不工作。

标签: mysqlnode.jsexpresspassport.js

解决方案


好吧,如果是getUserByEmail(),那么它不会返回一个连接到它的异步操作完成时的承诺,因此,doingawait getUserByEmail()不会等待任何事情。

await仅当您正在等待与您要等待的操作相关的承诺时才做一些有用的事情。由于您甚至没有等待承诺,因此await没有任何用处。您需要进行更改getUserByEmail(),以便它返回一个连接到您尝试等待的异步操作的承诺。

对于返回连接到异步操作的 Promise 的函数,您需要在该函数的任何地方使用基于 Promise 的异步操作,而不是普通的回调异步操作。这些都是数据库操作,所有现代数据库现在都有一个基于 Promise 的接口,所以你真正想要做的是切换.getConnection().query()并且.release()都使用基于 Promise 的操作。这也将使实现正确的错误处理和与错误调用者的正确通信变得更加简单。

我自己不是特别了解mysql,但这里有一个大概的想法。承诺接口来自模块mysql2/promise

const mysql = require('mysql2/promise');
const pool = mysql.createPool({...});

initializePassport(passport, async function(email) {
    let connection;
    try {
        connection = await pool.getConnection();
        console.log("Connected!");
        let result = await pool.query("SELECT * FROM users WHERE email = ?", email);
        return result[0];
    } catch(e) {
        // log the error and the rethrow so the caller gets it
        console.log(e);
        throw e;
    } finally {
        if (connection) {
            connection.release();
        }
    }
});

推荐阅读