【问题标题】:Nodejs - not sure how to await a database query within a functionNodejs - 不确定如何在函数中等待数据库查询
【发布时间】:2020-09-29 08:48:05
【问题描述】:

我是 nodejs 新手,正在努力掌握 async/await 功能。我已经阅读了许多其他 SE 帖子和许多博客,但似乎无法获得正确的代码组合来实现预期的程序流程。

我的程序的总体思路是调用 startNextPick() 函数,然后调用 getLeagueFromDraftPicks()。此函数内部是一个查询,需要“等待”完成,但我不确定执行此操作的正确/简单方法。目前,没有等待导致函数返回“未定义”结果。在这种情况下等待查询响应的正确/简单方法是什么?

startNextPick();

async function startNextPick(pickId) {
  console.log('A-- starting next pick');

  var leagueId = await getLeagueFromDraftPick(pickId);

  console.log('B-- leagueId from getLeagueFromDraftPick: '+leagueId);

  leagueId = Number(leagueId);
  if (leagueId > 0) {
    //.... do other stuff here
  } else {
    console.log('Error with finding league based on draft pick');
  }
}

async function getLeagueFromDraftPick(pickId) {
  pickId = Number(pickId);
  var leagueId;
  console.log('1 pickId: '+pickId);
  if (pickId  <= 0) {
    return false;
  }

  // Get LeagueID from draft based on pickId
  // *** Need to "await" this query "
  connection.query('select LEAGUE_ID from DRAFT where ID=? limit 1',
                  [pickId],
                  function (error, results, fields) {
    if (error) {
      console.log(error);
      return false;
    } else {
      leagueId = results[0].LEAGUE_ID;

      console.log('2--  pickId: '+pickId);
      console.log('3--  leagueId: '+leagueId);

      return leagueId;
    }
  });
  console.log('4--  leagueId: '+leagueId);
  return leagueId;
}

使用 console.log 跟踪代码的时间和流程,很明显需要等待查询,因为 getLeagueFromDraftPick() 的返回值显示未定义但查询结果最终显示正确。

Console.log output
****starting next pick****
A-- starting next pick
1 pickId: 19002
4--  leagueId: undefined
B-- leagueId from getLeagueFromDraftPick: undefined
Error with finding league based on draft pick
2--  pickId: 19002
3--  leagueId: 52

** 解决方案 ** 使用@cyberwombat 回答并进行一些修改,我能够让它工作。以下是工作代码:

async function startNextPick(pickId) {
  console.log('A-- starting next pick');

  var leagueId = await getLeagueFromDraftPick(pickId);

  console.log('B-- leagueId from getLeagueFromDraftPick: '+leagueId);
}


async function getLeagueFromDraftPick(pickId) {
  pickId = Number(pickId);
  console.log('1 pickId: '+pickId);
  if (pickId  <= 0) {
    return false;
  }

  // Get LeagueID from draft based on pickId
  // *** Need to "await" this query "
  const leagueId = await new Promise(function(resolve, reject)  {
    connection.query('select LEAGUE_ID from DRAFT where ID=? limit 1',
                    [pickId],
                    function (error, results, fields) {
      if (error) {
        console.log(error);
        reject(error);
      } else {
        if (results[0]) {
          console.log('2--  pickId: '+pickId);
          console.log('3--  leagueId: '+results[0].LEAGUE_ID);

          resolve(results[0].LEAGUE_ID);
        } else {
          resolve(0);        }
      }
    });
  });
  console.log('4--  leagueId: '+leagueId);
  return leagueId;
}


Console output:
****starting next pick****
A-- starting next pick
1 pickId: 19031
2--  pickId: 19031
3--  leagueId: 52
4--  leagueId: 52
B-- leagueId from getLeagueFromDraftPick: 52

【问题讨论】:

    标签: node.js asynchronous async-await


    【解决方案1】:

    连接位使用回调。为了让你的 async/await 可以很好地工作,你可以将它包装在一个 Promise 中(你也可以查看那个 db 库是否有一个 Promisified/async 版本)。理想情况下,您希望将其包装在 try/catch 块中以处理错误,但这是一个不同的故事。这是返回 1eagueId async 的代码。

    async function getLeagueFromDraftPick(pickId) {
      pickId = Number(pickId);
      var leagueId;
      console.log('1 pickId: '+pickId);
      if (pickId  <= 0) {
        return false;
      }
    
    
      const leagueId = await new Promise(function(resolve, reject)  {
        // Get LeagueID from draft based on pickId
        // *** Need to "await" this query "
        connection.query('select LEAGUE_ID from DRAFT where ID=? limit 1',
                      [pickId],
                      function (error, results, fields) {
          if (error) {
            console.log(error);
            reject(error)
    
          } else {
            leagueId = results[0].LEAGUE_ID;
    
            console.log('2--  pickId: '+pickId);
            console.log('3--  leagueId: '+leagueId);
    
            resolve(leagueId)
          }
        });
      })
    
      console.log('4--  leagueId: '+leagueId);
      return leagueId;
    }
    

    简化的可运行示例:

    // Create our async function
    async function getLeagueFromDraftPick() {
      console.log('1')
      // We can use the new Promise to wrap old style callbacks - not shown here
      const leagueId = await new Promise((resolve, reject) => {
        console.log('2')
        // Fake some delay - i.e. pretend w are doing some http request
        setTimeout(() => {
          resolve('foo')
         }, 1000);
      })
      console.log('3')
      return leagueId
    }
    
    // This weird parenthesis setup is just a trick to run async functions from the console
    (async () => {
      const leagueId = await getLeagueFromDraftPick()
      console.log(leagueId)
    })()

    【讨论】:

    • 在修复了您的答案中的一些问题(例如重复使用 LeagueId 变量)后,我在上面发布了最终解决方案。谢谢
    • 一个问题......虽然现在可以正常工作,但为什么控制台日志在消息 #2 和 3 之前显示消息 #4?返回值正在等待 Promise 的完成,所以代码流和 Promise 的工作方式让我感到困惑。 Promise 是否只阻止从父函数发送返回,而其他所有内容都继续执行?或者承诺应该像暂停一样,直到它被解决或被拒绝?
    • @BrianT 它不应该在 2/3 之前显示 4。我添加了一个可运行的 sn-p - 也许您的代码发生了一些不同的事情。在继续之前,承诺基本上会暂停并等待解决/拒绝。
    • 你展示的是我所期望的,但不是我所看到的。我将调用代码和控制台输出添加到我的解决方案中。看到任何可能导致无序日志的内容?
    • @BrianT - 这是因为您没有解决承诺。在我的第一个解决方案中,我确实错误地留下了 console.log('4-- leagueId: '+leagueId); 部分,而不是仅仅返回要解决的承诺。我现在已经编辑以匹配可运行的示例 - 在 new Promise 之前添加 await
    【解决方案2】:

    你应该试试这个: async function getLeagueFromDraftPick(pickId) { return new Promise((resolve, reject ) =&gt;{ pickId = Number(pickId); var leagueId; console.log('1 pickId: '+pickId); if (pickId &lt;= 0) { reject(false) ; }

    // Get LeagueID from draft based on pickId // *** Need to "await" this query " connection.query('select LEAGUE_ID from DRAFT where ID=? limit 1', [pickId], function (error, results, fields) { if (error) { reject(error ) ; } else { leagueId = results[0].LEAGUE_ID;

      `resolve(leagueId) ;`
    `}`
    

    }); console.log('4-- leagueId: '+leagueId); resolve(leagueId); }) }

    【讨论】:

    • 别忘了设置错误路径,这里可以使用promise拒绝。例如``` 拒绝(错误); ```
    猜你喜欢
    • 2021-06-21
    • 2016-10-29
    • 2023-01-31
    • 2019-06-16
    • 1970-01-01
    • 2015-07-09
    • 2021-03-29
    • 2018-01-15
    相关资源
    最近更新 更多