【问题标题】:Return for function after certain execution time在特定执行时间后返回函数
【发布时间】:2019-05-07 20:22:15
【问题描述】:

完全清楚,如果这很重要,我会在 Node 中执行此操作。

我有一个方法可以进行一些同步调用(它们依赖于下一次调用的反馈,所以必须是同步的),我对环境或我正在调用的东西没有太多控制权。

无论这些调用是否完成,我都需要在设定的时间(大约 3 秒)后返回一个值。如果这些调用已完成,则脚本完成并返回该值。一种备份超时,它返回一个可接受的(如果不完整的)值,而不是由于服务器执行限制而完全超时并引发错误。

我立即想到使用setTimeout()(如果没有跳闸,则使用​​clearTimeout())进行返回。但是,在 setTimeout 回调中返回一个值并不会结束我的脚本并返回该值,显然 - 那我该怎么办?

//"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";
}

试过

想做一个尝试-接住-投掷设置:

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";
}

...但是 catch 没有捕捉到它,这有点道理,因为抛出的错误超出了 try-catch 的范围,因为它是异步的......所以到目前为止我最好的想法是。

【问题讨论】:

  • 如果您包含更多关于您希望通过超时异步调用的函数的详细信息,这可能会有所帮助。
  • @ctt 这个函数 (myFunction) 是被调用的函数。它在内部做什么可能无关紧要,但只是几个 https 调用和围绕它们的一堆逻辑有时需要太长时间。

标签: javascript node.js return settimeout


【解决方案1】:

如果您将httpCall 函数中的延迟更改为小于 3 秒,那么您将得到hello 的输出

如果httpCall 的延迟超过 3 秒,那么您将得到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

【讨论】:

    【解决方案2】:

    setTimeout 实际上并不像 node js 事件循环那样工作。

    使用上面的实现,setTimeout 中的回调将永远不会被调用,因为clearTimeout 几乎会立即执行。倒计时时的 setTimeout 将允许在脚本中执行后续代码,这意味着 clearTimeout 将立即被调用,因为 scripttimmer 变量是真实的。

    要注意的另一件事是,如果您打算中断 setTimeout 执行其回调,则应仅使用 clearTimeout

    您可以尝试使用回调实现,这将允许您与返回变量进行交互,如下所示:

    const myFunction = async callback => {
        var scripttimer = setTimeout(function(){
            callback("my value");
        }, 3000);
    
        return "did this anyways";
    }
    
    myFunction(val => console.log(val));
    

    查看执行here

    此外,您应该避免使用async,除非您计划在您的函数中使用await

    【讨论】:

    • 如果其余的方法执行时间超过 3 秒,我需要超时来强制 myFunction 返回一个值。定时器设置和正常返回之间的同步远程调用意味着它可能需要超过 3 秒,或者可能需要更少。异步是调用功能的要求。我无法控制这叫什么。如果脚本执行时间少于 3 秒,我希望调用 cleartimeout 并且不触发超时回调。
    • 您可以尝试查看setImmediate。一个例子显示here
    • 这些东西都与 OP 没有任何关系
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多