使用promise实现超时 - 抛出错误

时间:2016-08-02 21:39:09

标签: javascript node.js promise cancellation

我试图使用promise和setTimeout为异步函数实现超时。我想运行异步操作,如果它在一段时间内没有完成,则抛出错误。目前,这就是我所拥有的:(其中一些在stackoverflow上找到)

function someOperation(cb) {
  setTimeout(function() {
    cb(null, 'Done');
  }, 2000);
}


var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    reject(new Error('Operation timed out'));
  }, 100);

  someOperation(function(err, res) {
    if (err) reject(err);
    else resolve(res);
  });

});

p.then(function(res) {
  console.log(res);
}, function(err) {
  console.log("Throwing error...")
  throw err;
});

但是在抛出错误时程序不会停止。是否有人能够告诉我为什么,以及是否有更简单的方法来做到这一点?我非常感激。

编辑:现在尝试第一次使用蓝鸟,它给someOperationPromised.timeout不是一个函数。我这样做了吗?

var Promise = require("bluebird");

function someOperation(cb) {
  setTimeout(function() {
    cb('', 'Done');
  }, 2000);
}

var someOperationPromised = Promise.promisify(someOperation);

someOperationPromised.timeout(1).then(function (){
  console.log("Finished!");
}).catch(Promise.TimeoutError, function (err) {
  throw err;
});

1 个答案:

答案 0 :(得分:4)

不确定您正在使用的诺言库,如果有的话。我可以建议Bluebird吗?它比原生更快,并具有很多很棒的功能。其中?超时。

来自documentation

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync("huge-file.txt").timeout(100).then(function(fileContents) {

}).catch(Promise.TimeoutError, function(e) {
    console.log("could not read file within 100ms");
});

修改

嘿那里!我花了一些时间对此进行排序,试图弄清楚为什么你的编辑不起作用。我的目标是向您证明.timeout()有效。此外,我想为您提供一个可行的解决方案,您可以使用Bluebird。

下面我添加了一个名为takesFourSeconds的函数。它返回一个将在4秒后解决的承诺。然后我拨打takesFourSeconds两次。我第一次使用超时强制承诺链拒绝,如果它需要超过3秒。如果花费的时间超过5秒,我第二次强制它拒绝。

var Promise = require("bluebird");

function takesFourSeconds (){
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            return resolve('hi');
        }, 4000);
    });
}

takesFourSeconds().timeout(3000).then(function(res) {
    console.log(res);
}).catch(Promise.TimeoutError, function(e) {
    console.log("promise took longer than 3 seconds");
});

takesFourSeconds().timeout(5000).then(function(res) {
    console.log(res);
}).catch(Promise.TimeoutError, function(e) {
    console.log("promise took longer than 5 seconds");
});

请注意,这会返回:

$ node index.js
promise took longer than 3 seconds
hi

正如所料。

小方注:

创建一个返回promise的函数时,您不必为在promise链中调用的每个函数创建一个新的promise。只有第一个功能。

例如,如果我想在takesFourSeconds()之后调用另一个函数,我可以这样写:

function myFunc(result){
  return result === 'hi' ? resolve('hey there') : reject('hi there');
}

然后:

takesFourSeconds()
  .then(myFunc) // myFunc will take in the resolved value of takesFourSeconds implicitly
  .then(result => console.log(result)
  .catch(error => console.log(error);

这应输出:

"hey there"

你有它! Bluebird.js中的超时。 :)