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

时间:2016-07-16 03:18:39

标签: javascript node.js asynchronous

考虑到我们想要在Node.js中执行一些需要一些时间才能完成的操作,比如说<?php require_once('admin_header.php'); ?> <div class="container"> <?php echo validation_errors(); ?> <div class="row"> <?php echo form_open('admin/store_article',['class'=>'form-horizontal']); ?> <?php echo form_hidden('user_id', $this->session->userdata('user_id'));?> <fieldset> <legend>Add Article</legend> <div class="row"> <div class="col-sm-6"> <div class="form-group"> <label for="inputEmail" class="col-lg-4 control-label">Title</label> <div class="col-lg-8"> <?php $data = array( 'name' => 'title', 'class' => 'form-control', 'value' => set_value('title'), 'placeholder' => 'Username' ); echo form_input($data); ?> </div> </div> </div> <div class="col-sm-6"> <?php echo form_error('title'); ?> </div> </div> <div class="row"> <div class="col-sm-6"> <div class="form-group"> <label for="inputPassword" class="col-lg-4 control-label">Article Body</label> <div class="col-lg-8"> <?php $data = array( 'name' => 'body', 'value' => set_value('body'), 'class' => 'form-control', 'placeholder' => 'Article Body', ); echo form_textarea($data); ?> </div> </div> </div> <div class="col-sm-6"> <?php echo form_error('body'); ?> </div> </div> <div class="row"> <div class="col-sm-6"> <div class="form-group"> <div class="col-lg-8 col-lg-offset-4"> <?php $data = array( 'name' => 'reset', 'class' => 'btn btn-default', 'value' => 'Reset', ); echo form_reset($data); ?> <?php $data = array( 'name' => 'submit', 'class' => 'btn btn-primary', 'value' => 'Submit', ); echo form_submit($data); ?> </div> </div> </div> </div> </fieldset> </form> </div> </div> <?php require_once('admin_footer.php'); ?> 。我们通常做的是传递一个类似的回调函数:

doHeavyWork()

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

如何在Node.js中完成?

1 个答案:

答案 0 :(得分:3)

您认为这可以通过简单的回调来实现,但我会为您说明问题

&#13;
&#13;
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)
})
&#13;
&#13;
&#13;

现在观看如果将3000更改为超过5000毫秒超时的值,会发生什么情况 - 例如,尝试10000。您会看到callback 被调用两次。这个不好!除非你想用大量的垃圾来破坏你的功能,否则不容易修复。

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

&#13;
&#13;
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) }
)
    
&#13;
&#13;
&#13;

现在看看如果再次将3000更改为10000会发生什么。承诺&#34;回调&#34;只会被调用一次

最后,使用Promise.race甚至可以更多地改进此代码。 Promise.race将返回一个新的Promise,只要其中一个输入Promises结算或拒绝,它就会解析或拒绝。这非常适合我们的用例。

最重要的是,请注意超时逻辑如何与doHeavyWork无法结合。这样可以保持您的功能整洁有序。

&#13;
&#13;
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) }
)
   
&#13;
&#13;
&#13;

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