【问题标题】:why my async await is not working properly为什么我的异步等待无法正常工作
【发布时间】:2026-02-11 22:15:01
【问题描述】:

我正在使用 express js 开发 api,在我的 api 调用中,我调用了 2 个函数,第一个是 login(),其他函数是 get_organizations(),但是 get_organization() 在没有完成 login() 函数的情况下被调用,我使用过async await 但它无法正常工作,有人可以帮我解决这个问题吗?我已经在这里添加了我的整个代码,

router.get('/', async (req, res) => {
    let token = await login();
    await get_organizations(token);
});

const get_organizations = async function (api_token) {
    try {
        console.log('Get List Of Organizations');
        console.log('Verifying token');
        let verify_token_data = await jwt.verify(api_token, config['token-secret']);
        console.log(verify_token_data);
        return false;      
    } catch (error) {
        console.log(error);
    }
}

const login = async function () {
    try {
        console.log('Login process started');
        const newToken = await jwt.sign({login:'login'},config['token-secret'],{ expiresIn: config['token-expires']});
        let username = 'root_admin'
        let password = 'Admin123';
        let token = String(cryptojs.lib.WordArray.random(20));
        console.log("token : "+token);
        await connection.query('SELECT * FROM users where username = ?  ',[username], async function(err, rows) {
            if (err) {
                console.log("Looged out failed");
            } else {
                const user = rows[0];
                console.log("psdsdsd");
                if(bcrypt.compareSync(password,user.passwordHash)) {
                    await connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId], async function(err, org_data) {
                        if (err) {
                            console.log("Looged out failed");
                        } else {
                            console.log("sdsd");
                            //console.log(org_data);
                            if(typeof org_data.name!='undefined') {
                                organization = org_data.name;
                            } else {
                                organization = 'VeriCurious';
                            }
                            //console.log(organization);
                            // create a token
                            const token = await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                                expiresIn: config['token-expires'] // expires in 30 minutes
                            }); 
                            console.log("Successfull loggedin");
                            console.log("New generated token : "+token);
                            return token;
                        }
                    });    
                }
            }    
        });

    } catch (error) {
        console.log(error);
    }
}

【问题讨论】:

  • 看来connetion.query 没有返回承诺。如果您希望等待它们,您需要研究如何将回调转换为 Promises。 async / await 建立在 Promise 之上。
  • 使用 node.js 内置的 'util.promisify' 方法将回调转换为 Promises

标签: node.js express node-modules


【解决方案1】:

当您在调用函数时使用await 时,您基本上是在等待该函数内部的一个promise 来解决。调用的函数旨在返回该承诺

在您的代码中,login 函数确实调用了connection.query,但没有任何承诺等待查询解决。

为了让await 真正等待connection.query,您需要返回一个Promise,它会在用户最终登录时解析 - 即您拥有令牌:

const login = async function () {
  try {
    console.log('Login process started');
    const newToken = await jwt.sign({login:'login'},config['token-secret'],{ expiresIn: config['token-expires']});
    let username = 'root_admin'
    let password = 'Admin123';
    let token = String(cryptojs.lib.WordArray.random(20));
    console.log("token : "+token);

    return new Promise(function(resolve, reject){

      connection.query('SELECT * FROM users where username = ?  ',[username], async function(err, rows) { // await won't do anything here,
      // you should only use await with functions that return promises.
        if (err) {
          console.log("Looged out failed");
          throw new Error(err);
        } else {
          const user = rows[0];
          console.log("psdsdsd");
          if(bcrypt.compareSync(password,user.passwordHash)) {
            await connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId], async function(err, org_data) {
              if (err) {
                console.log("Looged out failed");
                throw new Error(err);
              } else {
                console.log("sdsd");
                //console.log(org_data);
                if(typeof org_data.name!='undefined') {
                  organization = org_data.name;
                } else {
                  organization = 'VeriCurious';
                }
                //console.log(organization);
                // create a token
                const token = await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                  expiresIn: config['token-expires'] // expires in 30 minutes
                }); 
                console.log("Successfull loggedin");
                console.log("New generated token : "+token);
                resolve(token); // this signals the Promise to resolve.
                // return token;
              }
            });
          }
        }    
      });
    });
  } catch (error) {
      console.log(error);
  }
}

注意事项:

  1. Await 旨在使用 Promise。 javascript 中的异步函数,要么接受回调,要么返回 Promise。 connection.query 需要回调,所以 await 在那里没用。
  2. 您用来与数据库对话的模块 -mongoose?- 可能有一个承诺的 API。检查一下,因为如果您愿意使用 async/await,最好直接使用 Promises,而不是在新的 Promise 中包装代码。

例如,如果connection.query 返回了一个 Promise,你可以这样做:

const login = async function () {
  // skipped a lot of code and logic since this is an example
    const rows = await connection.query('SELECT * FROM users where username = ?  ',[username]);
    const user = rows[0];
    const org_data = await  connection.query('SELECT * FROM organizations where id = ?  ',[user.organizationId]);
    const organization = org_data.name;

    return await jwt.sign({ id: user.id, username: user.username, organizationId: user.organizationId, organization: organization}, config['token-secret'], {
                expiresIn: config['token-expires'] // expires in 30 minutes
  });
}

而且处理错误真的很简单。

  1. 当您在 async 函数内的回调中收到错误,并且您正在返回一个新的 Promise - 就像在我的示例中一样 - 我真的不知道是 reject 还是 throw 更好错误。我认为两者都会做同样的事情,但我不确定。

【讨论】:

  • 在几乎所有情况下投掷都会自动拒绝你的承诺。实际上,它唯一没有拒绝的情况是异常在 Promise 本身中被捕获。 Try / Catch 在异步函数中用于处理被拒绝的承诺异常/错误。或者,promise 上的 .catch() 方法也会自动捕获抛出的异常。 IMO,我更喜欢throw,因为它区分了由于非错误条件(例如超时)而被拒绝的承诺