javascript - 如果超过某个限制时间,如何在 Node.js 中完成一项操作?

标签 javascript node.js asynchronous

考虑一下,我们想要在 Node.js 中执行一些需要一些时间才能完成的操作,例如 doHeavyWork()。我们通常做的是传递一个回调函数,如下所示:

doHeavyWork(params, callbackFunction);

现在,我想为该操作的完成设定一个限制时间。我想要的是,如果该操作的正常运行时间超过限制时间,该函数将终止并通知回调已超出限制时间。

如何在 Node.js 中实现这一点?

最佳答案

您可能认为通过简单的回调就可以做到这一点,但我将向您说明一个问题

function doHeavyWork(params, callback) {
  // set the timeout
  var timeout = setTimeout(callback, 5000, Error('timeout'))
  
  // some debug message
  console.log('Please wait...')
  
  // begin heavy work
  // we sill simulate heavy work with setTimeout here
  setTimeout(function() {
    
    // if the function completed in time, clear the timeout
    clearTimeout(timeout)
    
    // callback without error
    callback(null, 'done')
  }, 3000)
}

// check to see it work
doHeavyWork('some params', function(err, res) {
  if (err)
    throw error
  else
    console.log(res)
})

现在观察如果将 3000 更改为超过 5000 毫秒超时的值,会发生什么情况 - 例如,尝试 10000。您将看到回调被调用两次。不是很好!除非你想用大量垃圾弄乱你的函数,否则修复起来并不容易。

如果我们使用 Promise,我们可以很容易地解决这个问题

function doHeavyWork(params) {
  return new Promise(function(resolve, reject) {
    // set the timeout
    var timeout = setTimeout(reject, 5000, Error('timeout'))

    // some debug message
    console.log('Please wait...')

    // begin heavy work
    // we sill simulate heavy work with setTimeout here
    setTimeout(function() {

      // if the function completed in time, clear the timeout
      clearTimeout(timeout)

      // callback without error
      resolve('done')
    }, 3000)
  })
}

// check to see it work
doHeavyWork('some params').then(
  function(res) { console.log(res) },
  function(err) { console.log(err.message) }
)
    

现在看看如果您再次将 3000 更改为 10000 会发生什么。 Promise“回调”只会被调用一次


最后,甚至可以使用 Promise.race 进一步改进此代码。 Promise.race 将返回一个新的 Promise,一旦输入 Promise 之一解析或拒绝,该 Promise 就会解析或拒绝。这非常适合我们的用例。

最重要的是,请注意超时逻辑如何与 doHeavyWork 耦合。这可以使您的功能保持干净且井井有条。

function doHeavyWork(params) {
  return new Promise(function(resolve, reject) {
    // some debug message
    console.log('Please wait...')

    // begin heavy work
    // we sill simulate heavy work with setTimeout here
    setTimeout(resolve, 3000, 'done')
  })
}

function timeout(ms) {
  return new Promise(function(resolve, reject) {
    setTimeout(reject, ms, Error('timeout'))
  })
}

// using Promise.race
Promise.race([
  timeout(5000),
  doHeavyWork('some params')
]).then(
  function(res) { console.log(res) },
  function(err) { console.log(err.message) }
)
   

在上面的代码示例中,将 5000 的超时值更改为更短的值,例如 1000 以查看错误情况

关于javascript - 如果超过某个限制时间,如何在 Node.js 中完成一项操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38407373/

相关文章:

javascript - 变量 this 不会返回我期望的结果

javascript - 将 div 部分链接到导航按钮

javascript - 删除多个圈子google maps api

node.js - 索引新文档并在同一查询中获取索引文档

rest - Rest api中的redis key 更新通知

javascript - ...args 和函数中的参数有什么区别

node.js - 如何在 ubuntu 16.04 上清理卸载 nodejs/node

json - 如何使用 `request` 模块传递变量

c# - 如何获得 Task.WhenAny 对 Task 和 CancellationToken 的影响?

asynchronous - EF6 - 在 Where() 子句中使用 await 关键字