【问题标题】:Using async.waterfall使用 async.waterfall
【发布时间】:2014-04-20 13:23:57
【问题描述】:

我正在使用 node.js 和 async 包。

这是我的代码:

async.waterfall(
[
    function(callback) {
        var data = getSomeData();
        callback(null, data);
    },
    function(data, callback) {
        someFunctionThatNeedsData(data);
        callback(null, 'done');
    }
],
function(err, result) {
}
);

getSomeData 有一个异步 HTTP 请求,它从 Web 服务中获取一些数据。我想等到收到回复,然后返回该数据并将其传递给someFunctionThatNeedsData

我的预期是 getSomeData(包括其中的回调)必须在继续调用 someFunctionThatNeedsData 之前完成。

问题在于,尽管在这里使用了waterfall 函数,但data 在到达someFunctionThatNeedsData 时是未定义的。

另外,从console.log 我可以看到getSomeData 的结尾是在getSomeData 内部的回调甚至开始之前到达的。

我是在错误地使用waterfall,还是这里的工具不正确?如果只是不正确,我可以使用什么来达到预期的效果?

或者我是否不得不接受深度嵌套的回调(在未来的工作中,我会这样做)并且必须通过将内联代码提取到命名函数中来缓解它?

【问题讨论】:

  • 如果 getSomeData 是一个异步方法,则该方法的期望是您不返回数据,而是通过回调来返回数据。然后在返回数据时,调用“回调”以移动到下一个函数。

标签: javascript node.js asynchronous async.js


【解决方案1】:

getSomeData() 有一个异步 http 请求,它从 Web 服务中获取一些数据。

这就是问题所在。执行流程已经继续到回调并执行它。这就是异步函数的工作原理!

您必须将回调传递给getSomeData,它会在 HTTP 请求完成后调用它。所以是的:您可能需要嵌套回调。

【讨论】:

  • 那么有没有办法阻止getSomeData在http请求的回调被调用之前返回?
  • @user3183922 除了发出同步请求(你应该):没有。
  • 好的。我来自 Java 背景,所以我可能(正如我所怀疑的那样)试图强制在 Javascript/node.js 上下文中不可能的模式。除了如果需要一段时间才能返回,您最终可能会阻止整个应用程序之外,还有其他不发出同步请求的主要原因吗?
  • @user3183922 目前我想不出任何一个,但肯定是一个很大的。
  • @user3183922 大多数 JS/node.js 库都是使用异步设计创建的。您应该以这种心态设计您的 JS/node.js 应用程序。
【解决方案2】:

如果你有异步操作。你不需要使用 async.waterfall。你可以以承诺链的方式做到这一点。

getSomeData().then(function(data) 
{
    var changeData = changeYourData(data);
    return changeData;
}).then(function(changedData)
{
    // some more stuff with it. You can keep on forwarding to the next `then` 
}).catch(function(err)
{
    // if any error throw at any point will get catch here
}).finally(function() 
{
    // this one will guarantee get call no matter what,
    // exactly the same like async.waterfall end of chain callback
});

此示例适用于 QWhen 以及任何符合标准的 Promise 库。

如果您需要使用 async.waterfall(因为您可以使用 Array.map 驱动它) 你只需要在你的then回调

async.waterfall(
[
    function(callback) {
        // A 
        getSomeData().then(function(data)
        {
            callback(null, data);
        });
        // B - just throw the whole thing in
        callback(null , getSomeData());
    },
    function(data, callback) {
        // A
        someFunctionThatNeedsData(data);
        // B
        data.then(function(resolvedData)
        {
             someFunctionThatNeedsData(resolvedData);
             callback(null, 'done');
        });
    }
],
function(err, result) {
});

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 2016-08-16
    • 2015-02-09
    • 1970-01-01
    • 2014-09-14
    • 1970-01-01
    • 2016-07-01
    • 2017-10-13
    • 2022-01-26
    • 1970-01-01
    相关资源
    最近更新 更多