DEV Community

Cover image for JavaScript Asynchronous function with Timeout
Ali Alp
Ali Alp

Posted on • Edited on

JavaScript Asynchronous function with Timeout

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);  
});
Enter fullscreen mode Exit fullscreen mode
//Output 
begin at 1550329812.264
end at 1550329814.267
Enter fullscreen mode Exit fullscreen mode

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);  
});
Enter fullscreen mode Exit fullscreen mode
//output 
begin at 1550332497.638
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode
//output 
begin at 1550339001.759
end at 1550339003.763
Enter fullscreen mode Exit fullscreen mode

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);
});
Enter fullscreen mode Exit fullscreen mode
//output 
begin at 1550339522.407
timeout at 1550339525.41
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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 :)

Top comments (0)