You can serialize the calls to axios and the logging of the results like this (but keep reading, we can also overlap the axios calls while still doing the output in order):
let queueLength = 0;
let sequencer = Promise.resolve();
function getAPIData(data){
const {symbol} = data;
++queueLength;
console.log("Added work item, queue length: " + queueLength);
sequencer = sequencer
.then(() => axios.get(`https://api.nasa.gov/planetary/apod?name=${symbol}`))
.then((newData) => {
console.log(newData);
})
.catch(error => {
// ...handle/report error...
})
.finally(() => {
--queueLength;
console.log("Completed work item, queue length: " + queueLength);
});
}
Live Example:
const rnd = (max) => Math.floor(Math.random() * max);
// Fake a sequence of socket.io events
for (let i = 0; i < 5; ++i) {
setTimeout(() => {
getAPIData({symbol: i});
}, 100 * (i + 1));
}
// Fake axios
const axios = {
get(url) {
console.log(`Start ${url}`);
const [, num] = /(\d+)$/.exec(url);
return new Promise(resolve => setTimeout(() => {
console.log(`End ${url}`);
resolve(num);
}, rnd(800)));
},
};
let queueLength = 0;
let sequencer = Promise.resolve();
function getAPIData(data){
const {symbol} = data;
++queueLength;
console.log("Added work item, queue length: " + queueLength);
sequencer = sequencer
.then(() => axios.get(`https://api.nasa.gov/planetary/apod?name=${symbol}`))
.then((newData) => {
console.log(newData);
})
.catch(error => {
// ...handle/report error...
})
.finally(() => {
--queueLength;
console.log("Completed work item, queue length: " + queueLength);
});
}
.as-console-wrapper {
max-height: 100% !important;
}
Here's how that works:
- We start with a fulfilled promise in
sequencer
.
- Each time
getAPIData
is called, it waits for the previous promise to be settled before doing the axios
call
- We assign the promise from the promise chain as the new value of
sequencer
so the next pass waits on it.
That does mean that each call to axios won't be done until the previous one finishes; there will never be any overlap. But if you just want the results in order, you can overlap the calls to axios, like this:
let queueLength = 0;
let sequencer = Promise.resolve();
function getAPIData(data){
const {symbol} = data;
++queueLength;
console.log("Added work item, queue length: " + queueLength);
sequencer = Promise.all([
sequencer,
axios.get(`https://api.nasa.gov/planetary/apod?name=${symbol}`)
])
.then(([, newData]) => { // Note the destructuring on this line
console.log(newData);
})
.catch(error => {
// ...handle/report error...
})
.finally(() => {
--queueLength;
console.log("Finished work item, queue length: " + queueLength);
});
}
That way, the axios calls can overlap, but we still do the logging in order.
Live Example:
const rnd = (max) => Math.floor(Math.random() * max);
// Fake a sequence of socket.io events
for (let i = 0; i < 5; ++i) {
setTimeout(() => {
getAPIData({symbol: i});
}, 100 * (i + 1));
}
// Fake axios
const axios = {
get(url) {
console.log(`Start ${url}`);
const [, num] = /(\d+)$/.exec(url);
return new Promise(resolve => setTimeout(() => {
console.log(`End ${url}`);
resolve(num);
}, rnd(800)));
},
};
let queueLength = 0;
let sequencer = Promise.resolve();
function getAPIData(data){
const {symbol} = data;
++queueLength;
console.log("Added work item, queue length: " + queueLength);
sequencer = Promise.all([
sequencer,
axios.get(`https://api.nasa.gov/planetary/apod?name=${symbol}`)
])
.then(([, newData]) => { // Note the destructuring on this line
console.log(newData);
})
.catch(error => {
// ...handle/report error...
})
.finally(() => {
--queueLength;
console.log("Finished work item, queue length: " + queueLength);
});
}
.as-console-wrapper {
max-height: 100% !important;
}
Example output of that:
Added work item, queue length: 1
Start https://api.nasa.gov/planetary/apod?name=0
Added work item, queue length: 2
Start https://api.nasa.gov/planetary/apod?name=1
Added work item, queue length: 3
Start https://api.nasa.gov/planetary/apod?name=2
End https://api.nasa.gov/planetary/apod?name=2
Added work item, queue length: 4
Start https://api.nasa.gov/planetary/apod?name=3
End https://api.nasa.gov/planetary/apod?name=0
0
Finished work item, queue length: 3
Added work item, queue length: 4
Start https://api.nasa.gov/planetary/apod?name=4
End https://api.nasa.gov/planetary/apod?name=3
End https://api.nasa.gov/planetary/apod?name=1
1
Finished work item, queue length: 3
2
Finished work item, queue length: 2
3
Finished work item, queue length: 1
End https://api.nasa.gov/planetary/apod?name=4
4
Finished work item, queue length: 0
Notice that even though the call for name=2
finished before the call for name=0
, 0
was logged before 2
.