NodeJS 异步回调未完成和渲染把手模板

Posted

技术标签:

【中文标题】NodeJS 异步回调未完成和渲染把手模板【英文标题】:NodeJS Async Callback is Not Finishing & Rendering Handlebars Template 【发布时间】:2017-07-03 14:25:17 【问题描述】:

我有一个 Express GET 请求,它从 Mongoose 查询中提取数据,对于返回的每个 doc,外部函数对作为 x 传递的每个 doc 执行计算并返回结果,以便我可以将它们呈现在前端使用 Handlebars。理想情况下,我想执行我的计算calcA, calcB, calcC, calcD,然后在为每个文档完成计算后,渲染test-env.hbs 模板。目前,当我调用它时,页面没有呈现,在日志中,一段时间后,它显示GET /test-env - - ms - -,大概是因为回调卡在某个地方。

快速 GET 请求

var updates = require('./updates.js');
app.get('/test-env', function(req, res, next)
        Market.find("marketname" : 'To Win')
            .then(function(doc)
                async.forEach(doc, function(x, callback)
                    updates.calcA(x);
                    updates.calcB(x);
                    updates.calcC(x);
                    updates.calcD(x);
                , function(err)
                    if(err)
                        return console.log(err);
                    res.render('test-env', title: 'Test Page', items: doc);
                );
        );
    );

典型的calc函数 我想将returnAreturnB 添加到docs 数据中,以便我可以在Handlebars 中的#each 表达式中呈现它

calcA: function(x) 
   Market.find("student": x.student, "marketname": x.marketname)
    .sort(btotal: -1)
    .limit(1)
    .then(function(ret) 
      var valueA = ret[0].btotal;
      var valueB = ret[0].back;
      Market.find("student": x.student, "marketname": x.marketname, "back": $lt: valueB)
      .sort(odds: -1)
      .limit(1)
      .then(function(doc) 
         var res = doc[0];
         if (res == null) 
           x.returnA = 0;
           x.returnB = 0;
          else 
           x.returnA = res.back;
           x.returnB = res.btotal;
         
     );
  );

【问题讨论】:

【参考方案1】:

看起来你实际上并没有调用你的回调函数。

            async.forEach(doc, function(x, callback)
                updates.calcA(x);
                updates.calcB(x);
                updates.calcC(x);
                updates.calcD(x);
                // <--- callback() needs to go here.
            

看:http://caolan.github.io/async/docs.html#each 该示例显示您需要显式调用 callback() 函数。

顺便问一下,您的计算(和回调函数)是否取决于doc 集合的内容顺序?因为async.forEach 方法实际上并不能保证doc 中的每个元素都将按照它们在集合中的顺序进行计算。因此,如果您是,那么值得考虑无序计算是否会导致不同的结果。

【讨论】:

嘿,Jty.tan,updates.calc() 函数不使用任何回调,它们都包含两个嵌套的 mongoose 调用,使用 .then(function(res1)) 用于外部 mongoose 查询,.then(function(res2)) 用于内部 mongoose询问。 calc 函数的执行顺序无关紧要,只要在渲染页面之前完成四个。我用你的方法试过了,还是加载不出来。【参考方案2】:

您没有在异步迭代器中调用回调。如果calc 函数是异步的,则应单独处理这些回调。如果它们不是异步的,普通的forEach 就可以了。

            ...
            async.forEach(doc, function(x, callback)
                updates.calcA(x);
                updates.calcB(x);
                updates.calcC(x);
                updates.calcD(x);
                callback(); // Call the callback to move on to the next item
            , function(err)
                if(err)
                    return console.log(err);
                res.render('test-env', title: 'Test Page', items: doc);
            );
            ...

【讨论】:

嘿 carebdayrvis,updates.calc() 函数不使用任何回调,它们都包含两个嵌套的 mongoose 调用,使用 .then(function(res1)) 用于外部 mongoose 查询,.then(function(res2)) 用于内部 mongoose 查询。 calc 函数的执行顺序无关紧要,只要在渲染页面之前完成四个。我用你的方法试过了,还是加载不出来。 您提供的calcA 函数是异步的。如果您希望该功能在呈现页面之前完成,您必须异步处理它。一种方法是承诺。看看这些:exploringjs.com/es6/ch_promises.htmlcaolan.github.io/async/docs.html#series

以上是关于NodeJS 异步回调未完成和渲染把手模板的主要内容,如果未能解决你的问题,请参考以下文章

如何优雅的处理Nodejs中的异步回调

nodejs基础 -- 回调函数

如何优雅的处理Nodejs中的异步回调

nodejs学习笔记 --回调函数

nodejs异步回调函数中this问题,求助

Nodejs学习笔记