我有一个API,该API在每分钟可以发送到该API提供的任何端点的请求数(50 /分钟)方面受到限制。
在下面的代码部分中,我将URL作为属性过滤对象orders
,每个具有提供数据的URL的对象都应存储在successfullResponses
中的app.component.ts
中。
Promise.all(
orders.map(order => this.api.getURL(order.resource_url).catch(() => null))
).then(responses => {
const successfulResponses = responses.filter(response => response != null)
for(let data of successfulResponses) {
// some other requests should be sent with data here
}
});
有超过50个orders
要检查,但是我一次只能检查最多50个orders
,因此我尝试在服务中处理它。我设置了发送第一个请求的第一个日期。之后,我将新请求的日期与第一个请求的日期进行比较。如果相差超过60,则将当前日期设置为新日期,然后将maxReq
再次设置为50。如果小于60,则检查是否还有剩余请求,如果是,则发送请求,否则返回我只等一分钟:
sleep(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
async getURL(){
if(!this.date){
let date = new Date();
this.date = date;
}
if((new Date().getSeconds() - this.date.getSeconds() > 60 )){
this.maxReq = 50;
this.date = new Date();
return this.http.get(url, this.httpOptions).toPromise();
} else {
if(this.maxReq > 0){
this.maxReq -= 1;
return this.http.get(url, this.httpOptions).toPromise();
} else{
console.log("wait");
await this.sleep(60*1000);
this.maxReq = 50;
this.date = new Date();
return this.http.get(url, this.httpOptions).toPromise();
}
}
}
但是app.component.ts
中的代码没有等待函数getURL()
,而是对请求执行了进一步的代码,这导致我发送“太多的请求太快”的问题。
我该怎么办?
答案 0 :(得分:1)
在尝试将诺言与多个异步功能一起使用时,我遇到了类似的问题。忘记是很容易的事情,但是为了让它们全部等待,您必须在调用有问题的函数的根行上使用await
。
我不确定,但是我的假设是您的await this.sleep(60*1000);
行确实在等待超时发生,但是在执行此操作的同时,称为getURL()
的代码正在执行其余的行,因为它在await
之前没有.then
(或类似的符号,例如getURL()
)。
在我的案例中,我发现此问题的方法是使用一个好的调试工具(我使用了Chrome DevTools自己的调试功能)。我建议您做同样的事情,在所有位置添加断点,并查看每行代码的去向。
下面是一个简短的粗略示例,以显示我的意思:
// This code increments a number from 1 to 2 to 3 and returns it each time after a delay of 1 second.
async function loop() {
for (i = 1; i <= 3; i++) {
console.log('Input start');
/* The following waits for result of aSync before continuing.
Without 'await', it would execute the last line
of this function whilst aSync's own 'await'
waited for its result.
--- This is where I think your code goes wrong. --- */
await aSync(i);
console.log('Input end');
}
}
async function aSync(num) {
console.log('Return start');
/* The following waits for the 1-second delay before continuing.
Without 'await', it would return a pending promise immediately
each time. */
let result = await new Promise(
// I'm not using arrow functions to show what it's doing more clearly.
function(rs, rj) {
setTimeout(
function() {
/* For those who didn't know, the following passes the number
into the 'resolved' ('rs') parameter of the promise's executor
function. Without doing this, the promise would never be fulfilled. */
rs(num);
}, 1000
)
}
);
console.log(result);
console.log('Return end');
}
loop();