【问题标题】:Node async/await don't work节点异步/等待不起作用
【发布时间】:2018-10-17 06:32:43
【问题描述】:

我试图在我的代码中使用更少的回调,所以我认为在使用 async/await 的解决方案中,但这不起作用,在查询完成之前快速发送渲染视图。

查询的结果很好,但是在渲染之后。

节点-v = 8.9.1

控制器代码:

app.get('/admin', ensureLoggedIn('/login'), (req, res, next) => {

  app.infra.connectionFactory(async (err, connection) => {  

    const blogDAO = new app.infra.BlogDAO(connection);

    const emailCount = await blogDAO.countLeads((errDAO, results) => {
    if (errDAO) {
        return next(errDAO);
    }
    return results[0].leads;
    });

    const userDAO = new app.infra.UserDAO(connection);
    const subCount = await userDAO.countUsers((errDAO, results) => {
    if (errDAO) {
        return next(errDAO);
    }
    return results[0].users;
    });

    const postCount = 3;

    res.render('admin/index', { emailCount, subCount, postCount });
  });
});

DAO 代码:

UserDAO.prototype.countUsers = function countUsers(callback) {
  this.connection.query('SELECT COUNT(token) AS users FROM users', callback);
};

【问题讨论】:

  • 您是否意识到await 仅适用于返回承诺以及该承诺与异步操作完成时间相关联的函数?您在一个接受回调但不返回承诺的函数上使用await blogDAO.countLeads(...)。它不会await 任何东西。事实上,countUsers() 根本没有返回值,所以 await 无事可做。您需要阅读更多关于 await 实际工作和正确使用的信息。
  • 问题:await能使异步代码同步吗?,回答:什么都没有可以使异步代码同步

标签: javascript node.js express async-await


【解决方案1】:

关键字 await 使 JavaScript 等待,直到该承诺完成并返回其结果。更多信息请查看here

您需要将代码更改为

DAO 代码

UserDAO.prototype.countUsers = function countUsers() {
  return this.connection.query('SELECT COUNT(token) AS users FROM users');
};

让 countUsers 函数返回一个承诺。

控制器代码

try {
    const result = await userDAO.countUsers();
    const subCount = result[0].leads; // Or anything that will work with result
} catch(err) {
    console.log(err); // Handle the error
}

等到承诺解决。如果解决,结果将在 subCount 中,如果发生拒绝或错误,则应由 catch 块处理。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以从使用像 bluebird 这样的 Promise 库开始,并通过回调来承诺事物。

    http://bluebirdjs.com/docs/api/promise.promisifyall.html

    类似:

    const Promise = require('bluebird');
    
    app.get('/admin', ensureLoggedIn('/login'), (req, res, next) => {
    
      app.infra.connectionFactory(async (err, connection) => {
    
        const blogDAO = Promise.promisifyAll(new app.infra.BlogDAO(connection))
        const results = await blogDAO.countLeadsAsync();
        const emailCount = results[0].leads;
    ....
    

    应该这样做。

    【讨论】:

      【解决方案3】:

      至少对我来说完成查询的最佳方法是使用异步模块,正如您所提到的,您希望在渲染方法之前执行查询。

      它有什么作用?运行一堆带有回调的函数并将结果保存在一个变量中。无需深究承诺!

      我在下面给出了一个例子。

      const all= require('../Model/all'); // This is the model which I'm calling
      const async=require('async');  // You need to install this one
      
      exports.edit = async function(req, res){
          id=req.params.id;
          table=req.params.table;
          department_companies=[];
          first_query=[];
          second_query=[];
      
          async.parallel({
                  record: async.apply(all.getRecord,table,id),
                  first_query: async.apply(all.viewPrimaryKeys,"first_table"),  // viewPrimaryKeys has 2 params: Table name and Callback
                  second_query: async.apply(all.viewPrimaryKeys,"second_table"),
              }
              ,function(err,results){
                  res.render('team/edit', {
                      id: id, 
                      record: results["record"],
                      first_query: results["first_query"],
                      second_query: results["second_query"]
                  });
              }
          );
      }
      

      对每个函数使用async.apply 对所有函数运行async.parallel,并在输出函数中使用res.render,希望对您有所帮助!

      【讨论】:

        猜你喜欢
        • 2020-06-11
        • 2016-12-26
        • 1970-01-01
        • 2019-12-19
        • 2023-03-27
        • 2021-06-18
        • 2023-04-07
        相关资源
        最近更新 更多