NODE - 等待一个api呼叫完成后再触发下一个api呼叫

时间:2017-01-19 13:36:30

标签: javascript node.js asynchronous

我正在我的一条路线add-users中发出POST请求。我创建了一个名为success的数组。一旦请求返回响应,我想触发下一个API调用。

目前我没有工作,因为我认为我也可以立即发送API请求。我认为解决方案是我等到第一个响应返回响应并完成,然后触发下一个API调用。

这个假设是否正确?如果是这样,任何人都可以建议如何实现这一点?我曾尝试使用.on('end'....

请参阅下面的代码。

app.get('/add-users', function (req, res) {

    var success = [];
    var count = 0;
    for(var i = 0; i < users.length; i++) {
        var name = users[i].userId;
        request({
            url: url,
            headers: {
                'Authorization': 'Bearer ' + users[i].accessToken,
                'Content-Type': 'application/json'
            },
            method: 'PUT',
            json: true
        }, function(err, resp, body){
            if (!err && resp.statusCode === 200) {
                success.push(name);
            }
        })
        .on('end', function(){
            console.log('this is the end');
            count++;
            if(count === users.length) {
                res.json(success);
            }
        });
    }
});

2 个答案:

答案 0 :(得分:1)

经典!当我第一次处理节点时,我也遇到过这个问题。

Lemme解释首先复制代码的某些部分:

app.get('/add-users', function (req, res) {
    // [...]
    for(/* user in users */) {
        request(/* [...] */)
        .on('end', function(){
            console.log('this is the end');
            count++;
            if(count === users.length) {
                res.json(success);
            }
        });
    }
});

与其他语言(例如Ruby)相比,Node执行非阻塞I / O.这意味着它异步执行几乎所有I / O操作(如发出HTTP请求)。基本上,当您发起请求时,它不会等待响应。

在你的循环中,这意味着它将一个接一个地发出所有请求而不等待他们的响应:

start loop
  make request
  make request
  make request
end of loop

... a little later
handle response
handle response
handle response

我认为你想要的是这样的:

start loop
  make request
  handle response
  make request
  handle response
  make request
  handle response
end of loop

我发现一个解决节点非阻塞性质并执行顺序请求的技巧是写一个递归函数,如下所示:

function getAllUsers(users) {
    function getOneUser(users) {
        let user = users.pop();
        request(/* [...] */)
            .on('end', function() {
                console.log("done with ONE user");
                if(users.length) { // do we still have users to make requests?
                    getOneUser(users); // recursion
                } else {
                    console.log("done with ALL users");
                    res.json(success);
                }
            });
    }

    // make a copy of the original users Array because we're going to mutate it
    getOneUser(Array.from(users)); 
}

以上操作是为一个用户发出一个请求,然后在响应到达时发出另一个请求。

我希望这会有所帮助。

答案 1 :(得分:0)

以下是我通常将多个请求链接在一起的方式。尝试在循环中调用异步函数将无法按照编写代码的方式工作。相反,我建议在初始请求的回调中调用下一个请求。

//set index
var index = 0;
function callAPI(user) {
    //increment index
    index++
    request({request:object},function(err, res){
      if (index <= users.length) {
        callAPI(users[index])
      }
    });
}
//call function with 0 index
callApi(users[0])

此外,如果您在上面的代码中使用console.log(name),您将看到自己的问题。