我使用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);
});
}
})
答案 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 functions和Array.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);
}
}