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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34255351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 17:26:56  来源:igfitidea点击:

Is there a version of setTimeout that returns an ES6 promise?

javascriptpromiseecmascript-6es6-promise

提问by Michael Kropat

Similar to this question, but rather than asking about how promises work in general, I specifically want to know:

this question类似,但不是询问promises一般是如何工作的,我特别想知道:

What is the standard/best way to wrap setTimeoutin something that returns a Promise? I'm thinking something like Angular's $timeoutfunction, but not Angular specific.

在返回Promise 的东西中包装setTimeout的标准/最佳方法是什么?我在想像 Angular's function这样的东西,但不是 Angular 特有的。$timeout

回答by Benjamin Gruenbaum

In Browsers

在浏览器中

First of all no - there is no built in for this. Lots of libraries that enhance ES2015 promises like bluebird whip with it.

首先不 - 没有为此内置。许多增强 ES2015 的库就像 bluebird 鞭子一样。

I think the other answer conflates executing the function and a delay, it also creates timeouts that are impossible to cancel. I'd write it simply as:

我认为另一个答案将执行函数和延迟混为一谈,它还创建了无法取消的超时。我会简单地写成:

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; 
}

Then you can do:

然后你可以这样做:

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

Or

或者

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

If we only want the basic functionality in ES2015, it's even simpler as:

如果我们只想要 ES2015 中的基本功能,那就更简单了:

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

In Node

在节点

You can use util.promisifyon setTimeoutto get a delayfunction back - meaning you don't have to use the new Promiseconstructor anymore.

您可以使用util.promisifyonsetTimeout返回一个delay函数——这意味着您不必再使用new Promise构造函数。

回答by Michael Kropat

Here's how I'd implement it:

这是我如何实现它:

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-syntax intentionally chosen)

(有意选择 ES5 语法)

But maybe there's a common library that already does this, or a better way to do it.

但也许有一个公共库已经这样做了,或者有更好的方法来做到这一点。

回答by vitalets

If you need the proper cancellation of promised timeoutsimilar to clearTimeout- returning the promise directly from setTimeoutis not convenient. Especially when using with ES7 async / awaitin try...finallyblock. It is better to have separate variable for timeout manipulation. I've implemented this approach as tiny await-timeoutpackage. It works as following:

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

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();
  }
}

In this example timeout will definitely be cleared in case of fetch success or any error and console.log('Timeout!')will not be called.

在这个例子中,超时肯定会在获取成功或任何错误的情况下被清除,并且console.log('Timeout!')不会被调用。