【问题标题】:How to use callbacks to wait for two queries async node如何使用回调等待两个查询异步节点
【发布时间】:2017-07-07 09:32:18
【问题描述】:

我在节点中使用异步模块瀑布方法进行 sql 查询。我将如何使用回调将两组数据发送到下一个函数。与将 qryUpdateCheck 和 qryCheckDbl 传递给下一个的第一个函数一样。这将如何正确完成。

async.waterfall([
    function (callback) {
        var requestUpdateCheck = new sql.Request([config]);
        requestUpdateCheck.query("Some qryUpdateCheck", function (err, qryUpdateCheck) {
            console.log('qryUpdateCheck', qryUpdateCheck);    
        });

        var requestCheckDbl = new sql.Request([config]);
        requestCheckDbl.query("Some qryRequestCheckDbl", function (err, recordset) {
            console.log('qryCheckDbl', qryCheckDbl);    
        });

        callback(null, qryUpdateCheck, qryCheckDbl);
    },
    function (qryUpdateCheck, qryCheckDbl, callback) {
        console.log('hi from second from qryUpdateCheck', qryUpdateCheck);
        console.log('hi from second from qryCheckDbl', qryCheckDbl);
        if ((qryUpdateCheck.length == 1) && (qryCheckDbl.length == 0)) {
            var requestUpdateLocID = new sql.Request([config]);

            requestUpdateLocID.query("Last qryUodateLocID", function (err, recordset) {
                console.log('qryUpdateLocID', recordset);
                callback(null, recordset);
            });
        } else if ((qryUpdateCheck.length == 0) && (qryCheckDbl.length == 0)) {
            var requestUpdateLocID = new sql.Request([config]);
            requestUpdateLocID.query("Insert qry", function (err, recordset) {
                console.log('qryUpdateLocID', recordset);
                callback(null, recordset);
            });
        }
    }
], function (err, result) {
  // result now equals 'done'
  console.log('done', result);
});

【问题讨论】:

  • 欢迎来到 StackOverflow!请花时间阅读有关如何回答问题的指南here
  • @ABusyProgrammer 这个问题很好。

标签: node.js express asynchronous callback async.js


【解决方案1】:

我发现async.auto 更适合这种情况。您将一个带有一组函数的对象传递给它,并且对于每个函数,您可以将其他函数名称作为依赖项传递。然后它将并行运行它可以并行执行的任何任务,同时确保具有依赖关系的函数等到它们都满足后才被调用。这有点像魔术。

var request = new sql.Request([config]);
async.auto({
  // this runs in parallel because it has no dependencies
  requestUpdateCheck: function(callback) {
    request.query("Some qryUpdateCheck", callback);
  },
  // this also runs in parallel because it has no dependencies
  requestCheckDbl: function(callback) {
    request.query("Some qryRequestCheckDbl", callback);
  },
  // this waits for the first two functions and then executes
  requestUpdateLocID: ['requestUpdateCheck', 'requestCheckDbl', function(results, callback) {
    console.log('Results from requestUpdateCheck and requestCheckDbl', JSON.stringify(results, null, 2));
    var qryUpdateCheck = results.requestUpdateCheck;
    var qryCheckDbl = results.requestCheckDbl;
    if ((qryUpdateCheck.length == 1) && (qryCheckDbl.length == 0)) {
      request.query("Last qryUodateLocID", function (err, recordset) {
        console.log('qryUpdateLocID', recordset);
        callback(err, recordset);
      });
    } else if ((qryUpdateCheck.length == 0) && (qryCheckDbl.length == 0)) {
      request.query("Insert qry", function (err, recordset) {
        console.log('qryUpdateLocID', recordset);
        callback(err, recordset);
      });
    }
  }]
}, function(err, results) {
  console.log('done:', err || results);
});

results 将包含来自所有已完成函数的数据。

这是一个非常简单的例子,有些人可能会认为promises.all 更适合。就个人而言,我发现async.auto 在事情变得更复杂时确实很有帮助。因此,为了保持一致性,我将它用于大多数异步控制流,并发现它可以处理大多数情况。

【讨论】:

  • 不错的建议,这感觉很像 gulp 和依赖任务。
  • 我试过了,requestUpdateLocID 中的结果返回为未定义
  • 啊,你必须使用 async.js v2 - 我使用的是旧版本...在函数中为 requestUpdateLocID 交换回调和结果参数 - 它在 v2 中发生了变化 - 我'已经更新了答案-应该是(results, callback)
【解决方案2】:

您可以进行嵌套并行调用。这是一个使用setTimeout的伪示例:

async.waterfall([
    function(callback) {
        async.parallel({
            requestUpdateCheck: function(callback) {
                setTimeout(function() {
                    callback(null, 'UpdateCheck')
                }, 500)
            },
            requestCheckDbl: function(callback) {
                setTimeout(function() {
                    callback(null, 'CheckDbl')
                }, 500)
            }
        }, function(err, result) {
            // here the parallel op is done
            callback(err, result);
        }) 
    },
    function(result, callback) {
        console.log('hi from second from qryUpdateCheck', result.qryUpdateCheck);
        console.log('hi from second from qryCheckDbl', result.qryCheckDbl);
        callback(null, result);
    }
], function(err, result) {
    // result now equals 'done'
    console.log('done', result);
});

【讨论】:

  • 我实际上并没有测试代码 - 可能是回调的名称应该更改。我会玩弄它。
  • @brandonscript,callback 在此处用于各种范围并不重要,因为 变量范围 将用于封闭范围 callback 值。 IE 最内层函数的作用域将在发生冲突时使用。
  • 是的,你是对的。我正在处理一些事情,但很快就会看看。
  • 它没有在瀑布的第二个函数中调用回调。在 2 个控制台日志之后
  • 现在它将结果作为错误传递 - 抱歉 :) - 我想它应该在 OP 原始示例的查询回调中传递 err
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2017-12-24
  • 2021-06-30
  • 2018-07-06
  • 2018-04-06
  • 1970-01-01
  • 2016-12-26
相关资源
最近更新 更多