How to ignore all old called async/await
functions if multiple async/await functions is called.
For example, this is my example.
let isLoading = false;
const onResponse = dateTime => {
console.log(dateTime);
isLoading = false;
}
const asyncFunction = async () => {
await delay(1000);
return new Date();
}
Now for example, if I called the function asyncFunction
3 times within 1 seconds, then I will take onResponse
3 times and my variable isLoading
work improperly.
function loadData() {
isLoading = true;
asyncFunction.then(onResponse);
}
How can I take response only from last call and ignore all earlier others.
How to ignore all old called async/await
functions if multiple async/await functions is called.
For example, this is my example.
let isLoading = false;
const onResponse = dateTime => {
console.log(dateTime);
isLoading = false;
}
const asyncFunction = async () => {
await delay(1000);
return new Date();
}
Now for example, if I called the function asyncFunction
3 times within 1 seconds, then I will take onResponse
3 times and my variable isLoading
work improperly.
function loadData() {
isLoading = true;
asyncFunction.then(onResponse);
}
How can I take response only from last call and ignore all earlier others.
Share Improve this question edited Mar 3, 2020 at 7:57 Nick Viatick asked Mar 3, 2020 at 7:35 Nick ViatickNick Viatick 2651 gold badge4 silver badges19 bronze badges 11- There is no native method to cancel a promise is js – Maheer Ali Commented Mar 3, 2020 at 7:45
- @MaheerAli so is there any way to handle this case? – Nick Viatick Commented Mar 3, 2020 at 7:47
-
Just overwrite the variable, and it will always contain the last value. If you want to wait till all three promises are resolved,
await Promise.all
. – Amadan Commented Mar 3, 2020 at 7:48 - 1 The point of debouncing it to ignore the stacking events, not cancelling the ones prior. – Robo Robok Commented Mar 3, 2020 at 7:54
- 1 OP wants to ignore the old calls, just like aborting fetch or Ajax. – Robo Robok Commented Mar 3, 2020 at 7:59
6 Answers
Reset to default 2I would just store some value and increment it every time you call your async function. Then, in the handler you can check if that value is still the same. If not, just return - it means that there was another call afterwards.
My answer was removed because I had sent directly link of debouncing. I have just wanted to explain what was in my head.
Here is the my solution that is like the below example. You can improve or change the code block depending on your needing. Simply it's canceled the previous calling. In my opinion, It's not the perfect solution. But one of the solutions to the problem.
const onResponse = dateTime => {
console.log(dateTime);
}
const asyncFunction = async () => {
await setTimeout(() => {}, 1000);
return new Date();
}
function debounce (callback, delay) {
let timeout;
return function (then) {
const that = this;
clearTimeout(timeout);
timeout = setTimeout(() => callback.apply(that, []).then(then), delay);
};
}
const debouncedFunction = debounce(asyncFunction, 100);
debouncedFunction(onResponse);
debouncedFunction(onResponse);
debouncedFunction(onResponse);
debouncedFunction(onResponse);
here's an implemetation of Robo Robok's answer (if you upvote me, upvote him too)
let isLoading = false;
let promiseCounter = 0;
const delay = time => new Promise(res => setTimeout(() => {res()}, time))
// use a destructuring assignement
const onResponse = ({dateTime, promiseId}) => {
// refuse promise if it was not the last
if (promiseId !== promiseCounter) {return;}
// reset counter to avoir overflow on really long run
promiseCounter = 0;
// do what needs to be done
console.log("onResponse", dateTime);
isLoading = false;
}
const asyncFunction = async () => {
const promiseId = ++promiseCounter;
await delay(1000);
return {dateTime: new Date(), promiseId};
}
function loadData() {
isLoading = true;
asyncFunction().then(onResponse);
}
(async ()=>{
// simulate multiple calls with a total interval > delay of one resposne
console.log("first call at", new Date())
loadData()
for (let i = 0; i < 100; i++) {
await delay(30);
loadData()
}
console.log("last call at", new Date())
})()
doc : destructuring assignement
If you only want the last pleted result something like this should work:
let finalResult;
const workFunc = async () => {
finalResult = new Date();
}
await Promise.all([ workFunc(), workFunc(), workFunc() ]);
console.log(finalResult);
The following code defines a function latest
that can be applied to a function to ensure only the latest call is run to pletion.
A variable curr
records the latest invocation by storing the latest promise. A function is configured in the then
position to mediate continuation. Progress along the promise chain is only permitted if the promise in progress is equal to curr
. ie. a subsequent invocation has not overwritten curr
in the interim.
So the following code prints out: stale two
.
function latest(fn) {
let curr = null
return (...args) => {
let p = fn(...args).then((result) => {
if(p === curr) return result
else throw 'stale'
})
curr = p
return p
}
}
const doSomething = (v, ms) => new Promise((r)=> setTimeout(() => r(v), ms))
const latestDoSomething = latest(doSomething)
latestDoSomething('one', 100).then(console.log).catch(console.log)
latestDoSomething('two', 100).then(console.log).catch(console.log)
You can use Promise.All:
await Promise.all([Call1(), Call2(), Call3(),...]).then(values => {
//values is [value1,value2,....,lastValue]
console.log(values[values.length-1]); last value is in the last entry
});