为什么我的代码尽管应该暂停但仍在执行?

时间:2020-05-22 12:52:23

标签: javascript angular typescript api asynchronous

我有一个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(),而是对请求执行了进一步的代码,这导致我发送“太多的请求太快”的问题。 我该怎么办?

1 个答案:

答案 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();