是否有返回ES6承诺的setTimeout版本?

时间:2015-12-13 19:31:19

标签: javascript promise ecmascript-6 es6-promise

this question类似,但不是询问承诺如何运作,我特别想知道:

setTimeout包裹在返回Promise的内容中的标准/最佳方法是什么?我正在考虑类似Angular的$timeout function,但不是Angular特定的。

3 个答案:

答案 0 :(得分:47)

在浏览器中

首先没有 - 没有内置的。许多增强ES2015的图书馆承诺像蓝鸟一样鞭打它。

我认为另一个答案会混淆执行功能和延迟,它还会产生无法取消的超时。我把它简单地写成:

function delay(ms){
    var ctr, rej, p = new Promise(function (resolve, reject) {
        ctr = setTimeout(resolve, ms);
        rej = reject;
    });
    p.cancel = function(){ clearTimeout(ctr); rej(Error("Cancelled"))};
    return p; 
}

然后你可以这样做:

delay(1000).then(/* ... do whatever */);

 doSomething().then(function(){ return delay(1000); }).then(doSomethingElse);

如果我们只想要ES2015中的基本功能,它甚至更简单:

let delay = ms => new Promise(r => setTimeout(r, ms));

在节点

您可以使用util.promisify上的setTimeout来获取delay函数 - 这意味着您不必再使用new Promise构造函数了。

答案 1 :(得分:4)

以下是我如何实施它:

function delay(duration, func) {
  var args = Array.prototype.slice.call(arguments, 2);

  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(func.apply(null, args));
    }, duration);
  });
}

(故意选择ES5语法)

但也许有一个共同的图书馆已经做到了,或者更好的方法。

答案 2 :(得分:1)

如果您需要与clearTimeout类似的正确取消承诺超时 - 直接从setTimeout返回承诺并不方便。特别是在try...finally块中使用ES7 async / await时。最好为超时操作设置单独的变量。我已经将这种方法实现为小await-timeout包。它的工作原理如下:

import Timeout from 'await-timeout';

async function foo() {
  const timeout = new Timeout();
  try {
    const fetchPromise = fetch('https://example.com');
    const timerPromise = timeout.set(1000).then(() => console.log('Timeout!'));
    await Promise.race([fetchPromise, timerPromise]);
  } finally {
    timeout.clear();
  }
}

在此示例中,如果获取成功或任何错误,肯定会清除超时,并且不会调用console.log('Timeout!')