如何获得未完成承诺的数量? [英] How to get the number of pending promises?
问题描述
我正在尝试创建一个函数,该函数使用以下逻辑发送HTTP请求:
I'm trying to create a function which sends HTTP requests with the following logic:
- 如果有5个或多个正在进行的请求,则下一个请求必须推迟到其中一个完成为止.只有这样才能处理下一个请求.
- 当响应代码不是200时,我最多希望重试该请求3次.如果重试3次后响应代码仍不是200,则应执行错误功能.
我如何知道正在进行的请求的数量?我该如何等到其中一个完成,然后才能处理下一个请求?
How can I know the number of ongoing requests? And how can I wait until one of them is completed so I can then process the next request?
这是到目前为止我尝试过的.count变量用于计算失败次数,但是我不知道如何计算未决的HTTP请求:
Here is what I have tried so far. The count variable is for counting the number of failures, but I don't know how to count pending HTTP requests:
var count = 0;
function get(url) {
return new Promise(function(resolve, reject) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", url, true);
xhttp.onload = function() {
if (xhttp.status == 200) {
resolve(JSON.parse(xhttp.response));
} else if (xhttp.status != 200 && count != 3) {
count++;
resolve(JSON.parse(xhttp.response));
} else if {
reject(xhttp.statueText):
} else(count == 3) {
reject("you have reached the maximum number of tries")
}
}
xhttp.onerror = function() {
reject(xhttp.statueText);
};
xhttp.send()
});
}
var promise = get("data/tweets.json);
promise.then(function(tweets) {
console.log(tweets);
};
我该如何进行这项工作?
How can I make this work?
推荐答案
这里是一种无需间隔计时器的方法.当下一个HTTP响应到达时,它使用函数队列来调用(这使得待处理的请求数低于5):
Here is a way to do it, where there is no need for an interval timer. It uses a queue of functions to call when the next HTTP response arrives (which makes the number of pending requests to come below 5):
var pending = 0;
var queue = [];
function get(url){
return new Promise (function(resolve,reject){
function loop(retries = 3) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET",url,true);
xhttp.onload = function(){
pending--;
if (xhttp.status == 200){
resolve(JSON.parse(xhttp.response));
}
else if (retries > 0) {
// retry by automatically relaunching the request:
loop(retries-1);
} else {
// give up
reject(xhttp.statusText); // correct your spelling!
}
if (pending < 5 && queue.length) {
// extract and execute the first of the queued actions:
queue.shift()();
}
};
xhttp.onerror= function(){
reject(xhttp.statusText); // correct your spelling
};
xhttp.send()
pending++;
}
if (pending >= 5) {
// Push the call we want to make for later execution in a queue:
queue.push(loop);
} else {
loop(); // try at the most 3 times
}
});
}
这是一个带有伪造的HTTPRequest对象的代码段,以便模拟有五个以上待处理请求时的延迟以及产生错误的请求.所有请求都需要1秒钟才能获得响应,尽管最后一个请求将产生错误状态并被重试3次,因此其承诺仅在3秒钟后解决:
Here is a snippet with a fake HTTPRequest object in order to simulate both the delay for when there are more than 5 pending requests, and a request that produces an error. All requests take 1 second to get a response, although the last one will produce an error status and will be retried 3 times, and as a consequence its promise only resolves after 3 seconds:
// Overwrite the real XMLHttpRequest with a dummy one, just for this snippet (skip this in your code!):
function XMLHttpRequest() {
this.open = function(_, url) {
this.status = url.indexOf('fail') > -1 ? 201 : 200;
this.response = JSON.stringify({text: 'Response from ' + url});
this.statusText = this.status == 200 ? 'OK' : 'Error status from ' + url;
};
this.send = function () {
setTimeout(this.onload.bind(this), 1000);
}.bind(this);
}
var pending = 0;
var queue = [];
function get(url){
return new Promise (function(resolve,reject){
function loop(retries = 3) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET",url,true);
xhttp.onload = function(){
pending--;
if (xhttp.status == 200){
resolve(JSON.parse(xhttp.response));
}
else if (retries > 0) {
// retry by automatically relaunching the request:
loop(retries-1);
} else {
// give up
reject(xhttp.statusText); // correct your spelling!
}
if (pending < 5 && queue.length) {
// extract and execute the first of the queued actions:
queue.shift()();
}
};
xhttp.onerror= function(){
reject(xhttp.statusText); // correct your spelling
};
xhttp.send()
pending++;
}
if (pending >= 5) {
// Push the call we want to make for later execution in a queue:
queue.push(loop);
} else {
loop(); // try at the most 3 times
}
});
}
// Example series of calls to illustrate the effect of more than 5 simultanious requests
// and the 3 retries for an error producing request:
console.log('start');
get('example.com?1').then( function(obj) { console.log(obj.text) });
get('example.com?2').then( function(obj) { console.log(obj.text) });
get('example.com?3').then( function(obj) { console.log(obj.text) });
get('example.com?4').then( function(obj) { console.log(obj.text) });
get('example.com?5').then( function(obj) { console.log(obj.text) });
get('example.com?6').then( function(obj) { console.log(obj.text) });
get('example.com?7').then( function(obj) { console.log(obj.text) });
get('example.com?fail').catch( function(msg) { console.log(msg) });
.as-console-wrapper { max-height: 100% !important; top: 0; }
这篇关于如何获得未完成承诺的数量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!