JavaScript Asynchronous function with Timeout

Ali Alp
3 min readFeb 16, 2019

If you have landed here so you are dealing with JavaScript async(Asynchronous) development. this article will explain a nice way of implementing timeout mechanism for a async function or any object which inherit from Promise object.

Issue

In a sunny day a basic asynchronous function is something like this :

function run(){
return new Promise((resolve,reject)=>{
//the task is going to take 2 seconds to be completed or it doesn’t matter we can wait for it’s completion
setTimeout(()=>{
resolve();
},2000);
});
}
console.log("begin at " + new Date().getTime()/1000);
run().then(()=>{
console.log("end at " + new Date().getTime()/1000);
});
//Output
begin at 1550329812.264
end at 1550329814.267

But the issue is eventually you will face with a situation like this:

function run(){
return new Promise(async(resolve,reject)=>{
//a task which may take n seconds to finish (0<n<?)
//in another word, we don't know how long it will take
await delay(100000)
resolve();
});
}
async function delay(time) {
return new Promise(function (resolve) {
setTimeout(resolve, time);
});
}
console.log("begin at " + new Date().getTime()/1000);
run().then(()=>{
console.log("end at " + new Date().getTime()/1000);
});
//output
begin at 1550332497.638

as it can be seen in above extreme example, when we don’t know the duration of the task’s execution or if we don’t have the luxury of waiting “forever” for the task to be finalized we will begin to think of a mechanism which can help us define a function with timeout functionality.

Solution

In the first sample below

async function run(timeout){
let ret= new Promise(async(resolve,reject)=>{
setTimeout(() => {
if (!ret.isResolved){
reject();
}
}, timeout);

//a task which may take n seconds to finish (0<n<?)
//in another word, we don't know how long it will take
await delay(2000)
resolve();
});
return ret;
}
async function delay(time) {
return new Promise(function (resolve) {
setTimeout(resolve, time);
});
}
console.log("begin at " + new Date().getTime()/1000);
run(3000).then(function(){
console.log("end at " + new Date().getTime()/1000);
}).catch(function(){
console.log("timeout at " + new Date().getTime()/1000);
});
//output
begin at 1550339001.759
end at 1550339003.763

the duration has been set to 2000 milliseconds which is lesser than our timeout value which is 3000 milliseconds, therefore the task will finish after 2000 milliseconds successfully but now let’s see what will happen if we set the duration of the task to a greater value to make the point of this article in the code below

async function run(timeout){
let ret= new Promise(async(resolve,reject)=>{
setTimeout(() => {
if (!ret.isResolved){
reject();
}
}, timeout);

//a task which may take n seconds to finish (0<n<?)
//in another word, we don't know how long it will take
await delay(100000)
resolve();
});
return ret;
}
async function delay(time) {
return new Promise(function (resolve) {
setTimeout(resolve, time);
});
}
console.log("begin at " + new Date().getTime()/1000);
run(3000).then(function(){
console.log("end at " + new Date().getTime()/1000);
}).catch(function(){
console.log("timeout at " + new Date().getTime()/1000);
});
//output
begin at 1550339522.407
timeout at 1550339525.41

As it can be seen we have successfully implemented a timeout mechanism, the logic is simple and reliable an simply can be shown below

async function run(timeout){
let ret= new Promise(async(resolve,reject)=>{
setTimeout(() => {
if (!ret.isResolved){
reject();
}
}, timeout);

await logRunningTask();
resolve();
});
return ret;
}
run(timeoutValue).then(success).catch(timeout);

I hope this mechanism will be useful for you as it was for me, I have found a lot of complicated approaches which had motivated me to come up with a simple and reliable solution :)

--

--

Ali Alp

“Take it easy” is nonsense , take it as hard as you can and don’t let it go :)