Reputation: 2318
I am trying to use the geocode API to get the json object by limiting the number of requests to 1 per second. I need to use async/await and this is what I have
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')
With this I am getting the following errors:
UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'getTime' of undefined
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
I tried to find why this is happening and when just print the requester object, I don't get the gettime() undefined error. Am I using async/await and promises correctly? What am I doing wrong?
EDIT: Based on the answers below, I no longer see the error, however I see 'Request Throttled'
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)
This is what I am seeing now:
{ success: false,
error: { code: '006', message: 'Request Throttled.' } }
Do I need to await for the response?
Upvotes: 3
Views: 2415
Reputation: 6778
According to geocode pricing options
Throttled API access is free. Rate limit: up to 1 API call per sec. API (Throttled to no more that 1 request per second for all free port users combined. eg., if 2 free requests come at the same time, each gets throttled to 2 seconds per request).
SO this would mean that as a free user you don't have control whether the limit would be 1 second or something else.
Upvotes: 1
Reputation: 18639
Arrow functions don't have this
, so this.lastrequest.getTime
is undefined
.
Use a normal function instead:
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)
And if you add a then(console.log)
, you can see the result!
Upvotes: 3
Reputation: 16908
Don't use =>
arrow functions inside object methods as the this
is not what you think it is.
The this
within the arrow function is the one that was in the current context where you defined the object, in your case it is pointing to the global object which has no lastRequest
property.
That is why this.lastRequest
is evaluating to undefined
.
You need to replace it with an anonymous function to correctly point to the this.lastRequest
property.
Also you won't get the data you want by simply returning it from the object method and assigning it to a variable as the value returned from your method is wrapped in a promise (due to the async
keyword) so you need to call then
on it to actually capture the data from the service.
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);
})
Some resources to look at:
Arrow functions as object methods
Upvotes: 2