我有以下代码。它遍历一组id并为每个id发出请求。我希望在完成所有请求后执行一些代码 - 比如100.如何做到这一点?
function initRequest(url){
request.get(topPostsUrl, function(err,response,body){
if(err) throw err;
handlePosts(body);
})
}
function handlePosts(posts){
var postsArray = JSON.parse(posts);
for(var i=0; i < postsCount; i++){
var targetUrl = itemUrl.replace("**id**", postsArray[i]);
request.get(targetUrl, function(err,response,body){
if(err) throw err;
processOutput(body,i+1);
})
}
}
function calthisFunctionAfterAllRequests () {
}
答案 0 :(得分:1)
使用Promises(MDN)和Promise.all
(MDN)函数等待所有请求的简单解决方案。
function initRequest(url){
request.get(topPostsUrl, function(err,response,body){
if(err) throw err;
handlePosts(body).then(calthisFunctionAfterAllRequests);
})
}
function doRequest(url) {
return new Promise(function(resolve, reject) {
request.get(url, function(err,response,body){
if(err) return reject(err);
return resolve(body);
})
})
}
function handlePosts(posts){
var postsArray = JSON.parse(posts);
var requests = [];
for(var i=0; i < postsCount; i++) {
var targetUrl = itemUrl.replace("**id**", postsArray[i]);
requests.push(doRequest(targetUrl));
}
// here is magic
return Promise.all(requests)
}
function calthisFunctionAfterAllRequests (requestsResult) {
// results store in requestsResult array in same order they added
}
答案 1 :(得分:1)
npm install --save request-promise
然后
var rp = require('request-promise');
function initRequest(url){
rp.get(topPostsUrl)
.then(body => {
handlePosts(body)
})
.catch(err => {
throw err
})
}
function handlePosts(posts){
var postsArray = JSON.parse(posts)
var arrayRequests = []
for(var i=0; i < postsCount; i++){
var targetUrl = itemUrl.replace("**id**", postsArray[i])
arrayRequests.push(
function(){
return rp
.get(targetUrl)
.then(() => {
return true
})
.catch(err => {
throw err
})
}
)
new Promise
.all(arrayRequests)
.then(() => {
calthisFunctionAfterAllRequests()
})
.catch(err => {
throw err
})
}
}
function calthisFunctionAfterAllRequests () {
}
答案 2 :(得分:1)
Promise.all有两个缺点:
如果任何promise失败,它们都会失败(不会调用处理成功请求的函数)。
您的所有请求都会立即开始。如果您有一个100个网址的数组,那么您将发出100个请求,并可能使您的请求目标不满意或锁定其运行的计算机的网络流量。
要解决第1点问题,您可以创建一个承诺数组来处理拒绝(失败)并返回Fail
个对象。处理结果时,您可以过滤掉失败的请求:
const doRequest = url =>
new Promise(
(resolve, reject) =>
request.get(
url,
(err,response,body) =>
(err)
? reject(err)
: resolve(body)
)
);
const Fail = function(reason){ this.reason = reason; }
const handlePosts = posts =>
Promise.all(
(JSON.parse(posts))
.map(
post => post.replace("**id**", post)
)
.map(
url => doRequest(url)
.then(
resolve=>resolve
,reject => new Fail(reject) //do not fail all requests just because one failed
)
)
)
doRequest(topPostsUrl)
.then(
handlePosts
)
.then(
// you can filter out failed request by: results.filter(r=>(r && r.constructor)!==Fail)
// you can filter out succeeded request by: results.filter(r=>(r && r.constructor)===Fail)
calthisFunctionAfterAllRequests
)
第2点可以通过throttling处理活动请求的数量来处理:上面的代码看起来像这样:
const max5 = throttle(5)
const handlePosts = posts =>
Promise.all(
(JSON.parse(posts))
.map(
post => post.replace("**id**", post)
)
.map(
url => max5(doRequest)(url)
.then(
resolve=>resolve
,reject => new Fail(reject) //do not fail all requests just because one failed
)
)
)
答案 3 :(得分:0)
这是抽象代码表示。
function RequestAll() {
for (var i = 1; i <= 100; i++) {
initRequest();
}
// return a promise
}
RequestAll.then(function() {
//whatever you need to do
});