Search code examples
javascriptnode.jsreturnsettimeout

Return for function after certain execution time


Full clarity, I'm doing this in Node if that matters.

I have a method that makes a few synchronous calls (they rely on the feedback of each call in the next, so must be synchronous) and I don't have much control over environment or the things I'm calling.

I need to return a value after a set time (about 3 seconds) whether or not those calls have completed. If those calls have completed, the script finishes and returns the value. A sort of backup timeout that returns an acceptable (if incomplete) value instead of timing out completely due to server execution limits and throwing an error.

I immediately think to use a setTimeout() (and a clearTimeout() if it's not tripped) to do the return. However, returning a value in the setTimeout callback doesn't end my script and return that value, obviously - so how would I?

//"myFunction" being consumed by something I don't have control over
//Otherwise I'd just wrap the caller in a timeout
myFunction = async () => {

    var scripttimer = setTimeout(function(){
        //emergency exit - script took longer than 3 seconds
        return "I need to return a value for myFunction now"; 
    }, 3000);

    //multiple synchronous remote https calls are made
    //right here which could sometimes cause this function
    //to take more than 3 seconds, at which point the 
    //scripttimer should kill myFunction by making it return 
    //a value. That's the part that I'm asking how to do, if 
    //even possible

    if (scripttimer){
        //if we took less than 3 seconds, we don't need the backup 
        //callback in scripttimer and so we're going to kill it
        clearTimeout(scripttimer);
    }

    //best scenario return value, script took less than 3 seconds
    return "did this anyways";
}

Tried

Thought to do a try-catch-throw setup:

try {

    var scripttimer = setTimeout(function(){
        throw "I need to return a value for myFunction now"; 
    }, 3000);

    //wait 4 seconds maybe
    if (scripttimer){
        clearTimeout(scripttimer);
    }
    return "I don't make it out if I take too long";


} catch (e){
    return "acceptable enough";
}

... but the catch doesn't catch it, which kinda makes sense since the error thrown is outside the scope of the try-catch since it's asynchronous... so there goes my best idea so far.


Solution

  • If you change the delay in httpCall function to less than 3 seconds then you will get the output as hello

    and if the delay in httpCall is more than 3 seconds then you will get the output as bye

    // Your Http Call Here which may take 3 seconds or more. eg.5 seconds
    
    
    function httpCall(){
      return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve("hello")
        },5000)
      });
    }
    
    // your main function where you will be calling sync functions
    function operation(){
      return new Promise((resolve,reject)=>{
        const timeoutID = setTimeout(function(){
            resolve("bye")
        },3000)
        httpCall().then(result=>{
           clearTimeout(timeoutID)
           resolve(result)
        })
      });
    }
    
    // This is how you should call
    operation().then((result)=>console.log(result))
    

    Check execution here