【问题标题】:Promise.race continuing to run after one promise rejectedPromise.race 在一个 Promise 被拒绝后继续运行
【发布时间】:2019-11-22 20:28:35
【问题描述】:

当其中一个被拒绝/解决时,promise.race 不应该终止所有承诺吗?

var cancelDeferred = new cancellation()

Promise.race([cancelDeferred.promise, new Promise( (res, req) => {
	setTimeout(() =>{
		console.log("hey")
	}, 2000)

})]).catch(e =>{
	console.log(e)
})

setTimeout(() => {cancelDeferred.cancel()}, 500);


function cancellation () {
    const token = {};
  
    token.promise = new Promise((_, reject) => {
      token.cancel = () => reject(new Error('cancelled'));
    });
  
    return token;
  }

在这段代码中,一个承诺在 500 毫秒后被取消,所以这应该导致 .catch 到控制台日志,对吗?

不,它仍然记录“嘿”,这是为什么呢?

【问题讨论】:

  • 不,承诺不能被“终止”。它不知道应该怎么做clearTimeout

标签: javascript promise cancellation


【解决方案1】:

这是正常行为。不是因为 Promise 拒绝,setTimeout 将被取消。 Promise.race 为您提供一个承诺,一旦任何给定的承诺被拒绝(或者如果所有承诺都满足,则满足)。它不会中断任何可能仍处于挂起状态的异步代码。在Promise.race-returned Promise 完成后,它将不知道传递给它的任何其他 Promise 的任何settlement,但不会阻止异步代码执行。

setTimeout 有自己的“契约”,只有调用 clearTimeout 才能破坏。任何 Promise 拒绝都不能阻止调用 setTimeout 回调。

要使其正常工作,您需要致电clearTimeout

var cancelDeferred = cancellation()
var clearDeferred = delay(2000);

Promise.race([cancelDeferred.promise, clearDeferred.promise]).catch(e =>{
    console.log("catch", e.message)
    clearDeferred.clear();
})

setTimeout(() => {cancelDeferred.cancel()}, 500);


function cancellation () {
    const token = {};
  
    token.promise = new Promise((_, reject) => {
        token.cancel = () => reject(new Error('cancelled'));
    });
    return token;
}

function delay(ms) {
    const token = {};

    token.promise = new Promise((resolve) => {
        const timer = setTimeout(() => {
            resolve(); // promise makes sense only if there is this call
            console.log("hey");
        }, ms);
        token.clear = () => {
            clearTimeout(timer);
            console.log("timer cleared");
        }
    });
    return token;
}

【讨论】:

  • 如果调用clearDeferred.clear()token.promise 会不会是一个始终未决的承诺?这会导致内存泄漏。
  • @crazyones110,如果计时器被清除,那么给setTimeout 的回调可以被垃圾回收。因此,还删除了对 Promise 的 resolve 函数的引用,这反过来又允许对 Promise 对象本身进行垃圾收集(如果它没有其他引用)。我看不出导致内存泄漏的原因。
猜你喜欢
  • 2022-01-20
  • 2020-08-01
  • 2016-05-18
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
  • 2016-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多