如何从setTimeout做出承诺

这个问题在这里已经有了答案:

  • 如何将现有的回调API转换为承诺? 17个答案

  • 更新(2017)

    在2017年,Promises被嵌入到JavaScript中,它们被ES2015规范添加(polyfills可用于过时的环境,如IE8-IE11)。 它们的语法使用一个回调函数传递给Promise构造函数( Promise executor),该函数接收解析/拒绝promise的函数作为参数。

    首先,由于async现在在JavaScript中有意义(即使它只是某些上下文中的关键字),我将later用作函数的名称以避免混淆。

    基本延迟

    使用本地承诺(或忠实的polyfill)它看起来像这样:

    function later(delay) {
        return new Promise(function(resolve) {
            setTimeout(resolve, delay);
        });
    }
    

    请注意,假定setTimeout的版本符合浏览器的定义,其中setTimeout不会将任何参数传递给回调,除非您在时间间隔后给予它们(这在非浏览器环境中可能不是这样,并且未使用在Firefox上是真实的,但是现在;在Chrome上甚至在IE8上都是如此)。

    具有价值的基本延迟

    如果你希望你的函数有选择地传递一个分辨率值,那么在任何模糊的现代浏览器上,你可以在延迟后给setTimeout额外的参数,然后在被调用时将它们传递给回调函数,你可以这样做(当前的Firefox和Chrome; IE11 +,想必Edge; 不是 IE8或IE9,不知道IE10):

    function later(delay, value) {
        return new Promise(function(resolve) {
            setTimeout(resolve, delay, value); // Note the order, `delay` before `value`
            /* Or for outdated browsers that don't support doing that:
            setTimeout(function() {
                resolve(value);
            }, delay);
            Or alternately:
            setTimeout(resolve.bind(null, value), delay);
            */
        });
    }
    

    如果您使用ES2015 +箭头功能,可以更简洁:

    function later(delay, value) {
        return new Promise(resolve => setTimeout(resolve, delay, value));
    }
    

    甚至

    const later = (delay, value) =>
        new Promise(resolve => setTimeout(resolve, delay, value));
    

    可取消的延迟与值

    如果您希望使取消超时成为可能,那么您不能仅仅从later返回承诺,因为承诺不能被取消。

    但是我们可以很容易地使用cancel方法和承诺的访问者返回对象,并在取消时拒绝承诺:

    const later = (delay, value) => {
        let timer = 0;
        let reject = null;
        const promise = new Promise((resolve, _reject) => {
            reject = _reject;
            timer = setTimeout(resolve, delay, value);
        });
        return {
            get promise() { return promise; },
            cancel() {
                if (timer) {
                    clearTimeout(timer);
                    timer = 0;
                    reject();
                    reject = null;
                }
            }
        };
    };
    

    现场示例:

    const later = (delay, value) => {
        let timer = 0;
        let reject = null;
        const promise = new Promise((resolve, _reject) => {
            reject = _reject;
            timer = setTimeout(resolve, delay, value);
        });
        return {
            get promise() { return promise; },
            cancel() {
                if (timer) {
                    clearTimeout(timer);
                    timer = 0;
                    reject();
                    reject = null;
                }
            }
        };
    };
    
    const l1 = later(100, "l1");
    l1.promise
      .then(msg => { console.log(msg); })
      .catch(() => { console.log("l1 cancelled"); });
    
    const l2 = later(200, "l2");
    l2.promise
      .then(msg => { console.log(msg); })
      .catch(() => { console.log("l2 cancelled"); });
    setTimeout(() => {
      l2.cancel();
    }, 150);
    链接地址: http://www.djcxy.com/p/55509.html

    上一篇: How to make a promise from setTimeout

    下一篇: Chaining promises with promises inside then()