处理来自 setTimeout 的错误

Posted

技术标签:

【中文标题】处理来自 setTimeout 的错误【英文标题】:How to handle errors from setTimeout in JavaScript? 【发布时间】:2017-05-16 20:13:13 【问题描述】:

关于 setTimeout 中函数的 try-catch 的简单问题

try 
    setTimeout(function () 
        throw new Error('error!');
    , 300)
 catch (e) 
    console.log('eeee!')
    console.log(e)

为什么不工作catch-block?

我能读到什么?

P.S:关于处理此类错误的可能性的问题。不要回答有关承诺的问题

【问题讨论】:

【参考方案1】:

计划与setTimeout 一起运行的函数在主循环中执行,在生成它们的代码体之外。

要处理错误,请将try-catch 放入setTimeout 处理程序中:

setTimeout(function () 
  try 
    throw new Error('error!');
   catch (e) 
    console.error(e);
  
, 300)

如果您需要从名为setTimeout 的块中访问Error 对象,请使用Promises:

const promise = new Promise((resolve, reject) => 
  setTimeout(function () 
    try 
      throw new Error('error!');
      resolve(); // if the previous line didn't always throw

     catch (e) 
      reject(e)
    
  , 300)
)

promise
  .then(result => console.log("Ok " + result))
  .catch(error => console.error("Ouch " + error))

上面的这个例子并不是处理Promise 的最优雅的方式。而是像这样实现delay(ms) 函数:

function delay(ms) 
  return new Promise(resolve => setTimeout(resolve, ms))

然后调用

delay(300).then(myFunction).catch(handleError)

【讨论】:

【参考方案2】:

有点奇怪的解决方案,但有时它可能会很有用......

function globalErrorHandler(e) 
  console.warn('eeee!')
  console.warn(e);


const _setTimeoutOriginal = setTimeout;
setTimeout = function(callback, timeout) 
  const args = Array.from(arguments).slice(2);
  _setTimeoutOriginal(function() 
    try 
      callback.apply(this, args);
     catch (e) 
      globalErrorHandler(e);
    
  , timeout);
;

setTimeout(function() 
  throw new Error('error!');
, 300)

【讨论】:

【参考方案3】:

你可以在这个Node.js官方doc找到很好的解释。

问题是当您的setTimeout() 函数的回调执行时,try catch(err) 块已经退出。另请注意,回调可能会使 Node.js 进程崩溃。

但是如果你想处理setTimeout()函数回调中的错误,那么你可以使用process全局EventEmitter对象来监听它们

process.on('uncaughtException', function(err)
  console.log(err)   
)

【讨论】:

这应该是公认的答案(提示,提示@Andrew Kochnev),因为它实际上解释了原因并且最彻底。 您可能会以损坏的 nodejs 进程结束。不要在不终止进程的情况下处理未捕获的异常。 nodejs.org/api/…【参考方案4】:

因为 catch 块在词法上包围了 setTimeout 调用,但这不是抛出的函数。 直接翻译,是

setTimeout(function () 
  try 
    throw new Error('error!');
   catch (e) 
    console.log('eeee!');
    console.log(e);
  
, 300);

【讨论】:

以上是关于处理来自 setTimeout 的错误的主要内容,如果未能解决你的问题,请参考以下文章

理解setTimeout()

setTime

在另一个函数中使用 setTimeout 时,“重载签名必须都是环境或非环境”

来自非静态函数的 SetTimer

Promise里捕捉错误的最佳实践

Js:没有函数参数的setTimeOut? [复制]