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

Populating async array with a function called right before.

本文关键字:填充 异步 数组 函数 调用      更新时间:2023-09-26
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);
});

I新到节点。问题是需要调用请求来填充请求回调数组。但问题是异步。Parallel将在请求数组满之前运行,并且需要运行所有回调。我在哪里移动这个异步,以便它在请求数组满后运行?

异步编程都是关于区块链的。这允许node有效地运行其事件队列,同时确保您的步骤按顺序完成。例如,下面是我编写的一个web应用程序的查询:

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.parallelfor (var x in list)循环完成之前运行。要强制async.parallel在循环结束后运行,需要一个计数器。

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

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

edit:您也可以将requests.push()部分写成:

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

我认为将b存储在valuesrequests中是多余的,但我保留了它。