节点在触发下一个请求之前等待来自一个GET请求的响应

时间:2016-11-24 11:41:54

标签: javascript node.js promise

我使用node连续两次调用API。

首先,我发出GET请求,然后我使用响应中的数据发出第二个GET请求。我想确保在触发第二个呼叫之前第一个API呼叫已经完成。

我尝试使用两个节点包request / request-promise向Spotify API发出服务器端GET请求。

最初,我使用的是request,但刚刚安装了request-promise。也许这不是必要的。请参阅下面的代码。谁能发现我正在犯的任何明显错误?我希望它能在following this post.

之后发挥作用
var request = require('request-promise');

request(url, function(error, response, body) {
  var body = JSON.parse(body);
  for (var i = 0; i < body.length; i++) {
    test.push(body[i].url)
  }

}
res.send(req.body);
}).then(function() {
  for (var i = 0; i < test.length; i++) {
    request(url2, function(error, response, body) {
      test2.push(body);
    });
  }
})

1 个答案:

答案 0 :(得分:0)

对你的问题使用request-promise是个好主意,因为promises可以更好地处理异步代码而不是回调,尤其是在处理多个请求和错误处理时。

但是,您对request-promise的使用不正确。你在这里的回调风格是request的工作方式,但不是承诺。

promises中的成功回调传递到then挂钩,而不是初始承诺构造。

此外,错误不会传递给success(first)回调,而是会被拒绝(第二次)回调(或者在catch钩子中)捕获。

对于第二个请求,您实际上是在尝试发出多个请求,一个请求在提供的数组中的每个url。为了确保在继续之前完成所有这些请求,您应该使用Promise.all

以下是使用request-promise构建承诺的方式。

request({ uri: url, json: true }) // this is how the docs for request-promise say you can request a json
  .then(function (json) { // accumulate array of urls and pass them along the promise chain
    var urls = [];
    for (var i = 0; i < json.length; i++) {
      urls.push(json[i].url)
    }
    return urls;
  })
  .then(function (urls) {
    var promises = [];
    for (var i = 0; i < urls.length; i++) {
      promises.push(request(urls[i])); // create a promise for each url and fire off the request
    }
    return Promise.all(promises); // continue down the chain once all promises (request) are resolved
  })
  .then(function (arrayOfResultsFromEachPreviousRequest) {
    // ...
  });

使用ES6 arrow functionsArray.prototype.map,您可以进一步减少代码:

request({ url: url, json: true })
  .then(json => json.map(item => item.url))
  .then(urls => Promise.all(urls.map(url => request(url))))
  .then(arrayOfResultsFromEachPreviousRequest => {
    // ...
  });

如果你想使用回调风格的request,事情会更加痛苦,尤其是等待多个请求的第二部分。

为了进行比较,这里是一种使用回调(hell)而没有错误处理的方法:

request.get({ url:url, json:true }, function(err, res, json) {
  var urls = [];
  for (var i = 0; i < json.length; i++) {
    urls.push(json[i].url)
  }
  makeRemainingRequests(urls, function(arrayOfResultsFromEachPreviousRequest) {
    // ...
  });
});

function makeRemainingRequests(urls, cb) {
  var results = new Array(urls.length).fill(false); // array holding the results of all requests
  for (var i = 0; i < urls.length; i++) {
    // wrap each request in an IIFE so we have a correct value of i
    (function(idx) {
      request(urls[idx], function(err, res, body) {
        results[idx] = body;
        // if all results obtained, call the callback
        if (results.every(function (res) { return !!res; })) {
          cb(results);
        }
      });
    })(i);
  }
}