I have an array of IDs and a fix endpoint that I need to call. So I want to foreach the array of IDs and make a corresponding rest API call for each ID. Since I don't want to "flood" the endpoint, I want to wait a second between each call. Also, I'd like to wait for the response before calling endpoint with a new ID.
Here's what I came up with:
// Code goes here
console.clear();
const url = 'some-domain/v1/api/users';
const ids = [1, 2, 3, 4, 5, 6, 7];
const serviceMock = (id) => new Promise((resolve, reject) => {
console.log('Got request for id ' + id);
setTimeout(() => {
resolve(`${url}${id} returned ${ Math.floor((Math.random() * 100) + 1)}`);
}, 2000);
});
const main = async() => {
let index = 0;
for (let id of ids) {
index++;
setTimeout(async() => {
const data = await serviceMock(id);
console.log(`Done for user ${id}!`);
console.log(data);
}, 1000 * index);
}
};
main();
The setTimeout
in serviceMock is used to simulate the rest API call, and the setTimeout
in main
is used to pause between the calls.
Now, how I would like it to behave is as follows (in console):
Got request for id 1
Done for user 1!
some-domain/v1/api/users1 returned 77
Got request for id 2
Done for user 2!
some-domain/v1/api/users2 returned 75
Got request for id 3
Done for user 3!
some-domain/v1/api/users3 returned 26
Got request for id 4
Done for user 4!
some-domain/v1/api/users4 returned 44
Got request for id 5
Done for user 5!
some-domain/v1/api/users5 returned 79
Got request for id 6
Done for user 6!
some-domain/v1/api/users6 returned 52
Got request for id 7
Done for user 7!
some-domain/v1/api/users7 returned 34
This is what I get:
Got request for id 1
Got request for id 2
Got request for id 3
Done for user 1!
some-domain/v1/api/users1 returned 77
Got request for id 4
Done for user 2!
some-domain/v1/api/users2 returned 75
Got request for id 5
Done for user 3!
some-domain/v1/api/users3 returned 26
Got request for id 6
Done for user 4!
some-domain/v1/api/users4 returned 44
Got request for id 7
Done for user 5!
some-domain/v1/api/users5 returned 79
Done for user 6!
some-domain/v1/api/users6 returned 52
Done for user 7!
some-domain/v1/api/users7 returned 34
Here's a working example:
what exactly am I missing here?
I have an array of IDs and a fix endpoint that I need to call. So I want to foreach the array of IDs and make a corresponding rest API call for each ID. Since I don't want to "flood" the endpoint, I want to wait a second between each call. Also, I'd like to wait for the response before calling endpoint with a new ID.
Here's what I came up with:
// Code goes here
console.clear();
const url = 'some-domain./v1/api/users';
const ids = [1, 2, 3, 4, 5, 6, 7];
const serviceMock = (id) => new Promise((resolve, reject) => {
console.log('Got request for id ' + id);
setTimeout(() => {
resolve(`${url}${id} returned ${ Math.floor((Math.random() * 100) + 1)}`);
}, 2000);
});
const main = async() => {
let index = 0;
for (let id of ids) {
index++;
setTimeout(async() => {
const data = await serviceMock(id);
console.log(`Done for user ${id}!`);
console.log(data);
}, 1000 * index);
}
};
main();
The setTimeout
in serviceMock is used to simulate the rest API call, and the setTimeout
in main
is used to pause between the calls.
Now, how I would like it to behave is as follows (in console):
Got request for id 1
Done for user 1!
some-domain./v1/api/users1 returned 77
Got request for id 2
Done for user 2!
some-domain./v1/api/users2 returned 75
Got request for id 3
Done for user 3!
some-domain./v1/api/users3 returned 26
Got request for id 4
Done for user 4!
some-domain./v1/api/users4 returned 44
Got request for id 5
Done for user 5!
some-domain./v1/api/users5 returned 79
Got request for id 6
Done for user 6!
some-domain./v1/api/users6 returned 52
Got request for id 7
Done for user 7!
some-domain./v1/api/users7 returned 34
This is what I get:
Got request for id 1
Got request for id 2
Got request for id 3
Done for user 1!
some-domain./v1/api/users1 returned 77
Got request for id 4
Done for user 2!
some-domain./v1/api/users2 returned 75
Got request for id 5
Done for user 3!
some-domain./v1/api/users3 returned 26
Got request for id 6
Done for user 4!
some-domain./v1/api/users4 returned 44
Got request for id 7
Done for user 5!
some-domain./v1/api/users5 returned 79
Done for user 6!
some-domain./v1/api/users6 returned 52
Done for user 7!
some-domain./v1/api/users7 returned 34
Here's a working example: http://plnkr.co/edit/sNfk8GIfqbhrpql5hQ16?p=preview
what exactly am I missing here?
Share asked Nov 7, 2017 at 12:59 uglycodeuglycode 3,0927 gold badges32 silver badges57 bronze badges 5-
You never wait for the
setTimeout
callback. In fact you cannotawait
a callback, you can only wait for a promise - just create one for the delay, exactly like you already demonstrated inserviceMock
. – Bergi Commented Nov 7, 2017 at 13:01 -
hmm, something like this? plnkr.co/edit/7n6ysTt0tn9UdlUV7ppp is it still necessary to do this in
setTimeout
:1000 * index
? – uglycode Commented Nov 7, 2017 at 13:06 -
Yes, something like that, however a) put the
serviceMock(id)
in its ownawait
after the delay, not inside the callback b) make a helper function for the delay promise c) you don't need the multiplication any more – Bergi Commented Nov 7, 2017 at 13:11 - Oh, so you think a solution like user 'Sunday' suggested below? Something in this manner plnkr.co/edit/ruzf09vqMspps6JEjxTo?p=preview – uglycode Commented Nov 7, 2017 at 13:21
- Yes, exactly what he suggested. – Bergi Commented Nov 7, 2017 at 13:27
2 Answers
Reset to default 4Don't put 'await' in setTimeout.
I suggest you write wait function:
const wait = ms => new Promise(
(resolve, reject) => setTimeout(resolve, ms)
);
Now you can easily type:
const main = async () => {
let index = 0;
for (let id of ids) {
index++;
await wait(1000);
const data = await serviceMock(id);
console.log(`Done for user ${id}!`);
console.log(data);
}
};
main();
A simple recursive solution:
create a variable var i = 0
to hold the current index of your ID array.
Next create a function x()
that makes your API call. In the success function of your API call, increment i
i.e the current index of your ID array, then do a check i == array.length
if true do nothing if false call function x()
again.