使用之前调用的函数填充异步数组。

时间:2014-07-05 03:24:02

标签: javascript node.js

var request = require('request'),
requests = [],
values = [],

request("url1", function());

function() {
.....
  for (x in list){
   requests.push(requestFunction(x));
  }
}

requestFunction(x){
  request("url2", function (e,r,b) {
    ....
    return function(callback) {
    values[i] = b
    }
  });
}

async.parallel(requests, function (allResults) {
    // values array is ready at this point
    // the data should also be available in the allResults array
    console.log(values);
});

我是节点新手。问题是需要调用请求来填充请求回调数组。但问题是async.parallel将在请求数组已满并且需要运行所有回调之前运行。我在哪里移动此异步,以便在请求数组已满后运行?

1 个答案:

答案 0 :(得分:2)

异步编程就是链接块。这允许节点有效地运行其事件队列,同时确保您的步骤按顺序完成。例如,这是来自我写的网络应用程序的查询:

app.get("/admin", isLoggedIn, isVerified, isAdmin, function (req, res) {
    User.count({}, function (err, users) {
        if (err) throw err;
        User.count({"verified.isVerified" : true}, function (err2, verifiedUsers) {
            if (err2) throw err2;
            Course.count({}, function (err3, courses) {
                // and this continues on and on — the admin page
                // has a lot of information on all the documents in the database
            })
        })
    })  
})

注意我是如何在彼此内部链接函数调用的。 Course.count({}, ...)只能在调用User.count({"verified.isVerified" : true}, ...)后调用。这意味着永远不会阻止i / o,并且在没有所需信息的情况下永远不会呈现/admin页面。

你没有真正提供有关你的问题的足够信息(所以可能有更好的方法来解决它),但我认为你现在可以这样做:

var request = require('request'),
    requests = [],
    values = [],
    length;     // a counter to store the number of times to run the loop

request("url1", function() {

    length = Object.keys(list).length;
    // referring to the list below;
    // make sure list is available at this level of scope

    for (var x in list){
        requests.push(requestFunction(x));
        length--;
        if (length == 0) {
            async.parallel(requests, function (allResults) {
                console.log(values);    // prints the values array
            });
        }
    }
}

function requestFunction(x) {
    request("url2", function (e,r,b) {
        values[i] = b;
        return b;
    }
}

我假设requestFunction()需要一段时间才能加载,这就是async.parallel循环结束前for (var x in list)运行的原因。要在循环结束后强制async.parallel运行,您需要一个计数器。

var length = Object.keys(list).length;

这将返回list关联数组(又名对象)中的键数。现在,每次运行for循环时,都会递减length。在length == 0后,您可以运行async.parallel流程。

编辑:您还可以将requests.push()部分写为:

requests.push(
    (function () {
        request("url2", function (e,r,b) {
            values[i] = b;
            return b;
        }
    })()
);

我认为在bvalues中存储requests是多余的,但我保留了它,就像你拥有它一样。