Node.js:尝试对服务器的请求数量进行限制时如何使用异步/等待

时间:2019-02-05 05:52:10

标签: javascript node.js

我试图通过将请求数限制为每秒1个,使用地址解析API来获取json对象。我需要使用async / await,这就是我所拥有的

const requester = {
    lastRequest: new Date(),
    makeRequest: async (url) => {
        var timestart = new Date()
        // first check when last request was made
        var timeSinceLast = (timestart).getTime() - this.lastRequest.getTime();
        if (timeSinceLast < 1000) {
            await new Promise(resolve => setTimeout(resolve, timeSinceLast));
        }
        const response = await fetch(url);
        const json = await response.json();
        return json;
        // make request here and return result
    }
};
var requestResponse = requester.makeRequest('https://geocode.xyz/?
     locate=Warsaw,Poland&json=1')

与此相关的是以下错误:

  

UnhandledPromiseRejectionWarning:TypeError:无法读取属性   未定义的“ getTime”

     

UnhandledPromiseRejectionWarning:未处理的承诺拒绝。这个   由抛出异步函数引起的错误   没有障碍,或者拒绝了没有处理的承诺   使用.catch()。 (拒绝ID:1)

我试图找出原因,仅打印请求者对象时,没有得到gettime()未定义错误。我在使用async / await并正确承诺吗?我在做什么错了?

编辑:基于以下答案,我不再看到错误,但是我看到“请求已限制”

const requester = {
   lastRequest: new Date(),
   makeRequest: async function(url){
       var timestart = new Date()
       // first check when last request was made
       var timeSinceLast = (timestart).getTime() - this.lastRequest.getTime();
       if (timeSinceLast < 1000) {
           await new Promise(resolve => setTimeout(resolve, timeSinceLast));
       }
       const response = await fetch(url);
       const json = await response.json();
       return json;
       // make request here and return result
   }
};
requester.makeRequest('https://geocode.xyz/?locate=Warsaw,Poland&json=1') 
.then(console.log) 

这就是我现在看到的:

{ success: false,
 error: { code: '006', message: 'Request Throttled.' } }

我需要等待答复吗?

3 个答案:

答案 0 :(得分:3)

Arrow functions don't have this,因此this.lastrequest.getTimeundefined

改为使用普通函数:

const requester = {
    lastRequest: new Date(),
    makeRequest: async function(url){
        var timestart = new Date()
        // first check when last request was made
        var timeSinceLast = (timestart).getTime() - this.lastRequest.getTime();
        if (timeSinceLast < 1000) {
            await new Promise(resolve => setTimeout(resolve, timeSinceLast));
        }
        const response = await fetch(url);
        const json = await response.json();
        return json;
        // make request here and return result
    }
};
requester.makeRequest('https://geocode.xyz/?locate=Warsaw,Poland&json=1') //Don't write strings in two lines
.then(console.log)

如果您添加then(console.log),则可以看到结果!

答案 1 :(得分:2)

不要在对象方法中使用=>箭头功能,因为this不是您想的那样。

箭头函数中的this是在您定义对象的当前上下文中的对象,在您的情况下,它指向没有lastRequest属性的全局对象。

这就是this.lastRequest评估为undefined的原因。

您需要用匿名函数替换它,以正确指向this.lastRequest属性。

通过简单地从对象方法返回数据并将其分配给变量(由于方法返回的值包含在promise中),您也无法获得所需的数据(由于async关键字)因此您需要在其上调用then才能从服务中捕获数据。

const requester = {
    lastRequest: new Date(),
    makeRequest: async function(url) {
        var timestart = new Date();
        // first check when last request was made
        var timeSinceLast = timestart.getTime() - this.lastRequest.getTime();
        if (timeSinceLast < 1000) {
            await new Promise(resolve => setTimeout(resolve, timeSinceLast));
        }
        const response = await fetch(url);
        const json = await response.json();
        return json; //wrapped in a promise
        // make request here and return result
    }
};
var requestResponse = requester.makeRequest('https://geocode.xyz/?locate=Warsaw,Poland&json=1').then((data)=>{
   console.log(data);
})

要查看的一些资源:

Arrow functions as object methods

Async function

答案 2 :(得分:1)

根据geocode pricing options

  

受限制的API访问是免费的。速率限制:每秒最多1个API调用。 API(将所有空闲端口用户的总访问速度限制为每秒不超过1个请求,例如,如果同时有2个自由请求,则每个请求的限制时间为2秒)。

因此,这意味着作为自由用户,您无法控制限制是1秒还是其他时间。