javascript 与Promise.race()实现作斗争

euoag5mw  于 2023-01-29  发布在  Java
关注(0)|答案(2)|浏览(137)

我看到以下Promise.race()的实现。
我觉得很难理解,它是如何工作的。

const race = function(promisesArray) {
  return new Promise((resolve, reject) => {
    promisesArray.forEach((innerPromise) => {
      Promise.resolve(innerPromise)
        .then(resolve, reject) 
        .catch(reject);
    });
  });
};

第一部分:下面的陈述是真的吗?
Promise.resolve(innerPromise)将始终返回innerPromise作为值的已解析的promise,并且由于它始终解析,因此I将始终在.then block中结束。
第二部分:
我在解释中读到解析和拒绝传递给.then块将在innerPromise解析时被调用。为什么?,它不应该是Promise。resolve(innerPromise)总是解析,总是.then块的第一个回调应该被调用?
我想我错过了一些非常基本的东西。我已经试图找到解决办法,但未能找到一个解释,以消除我的疑虑。

c90pui9n

c90pui9n1#

代码中Promise.resolve的作用是允许数组元素不是承诺,它们可以是任意的thenable,也可以是正则值(这将成为真正实现的承诺)。

const existingValue = 5;
const existingPromise = Promise.reject(new Error("blah"));
const existingThenable = {
    then() {
        console.log("never going to resolve >:)");
    }
};

Promise.race([existingValue, existingPromise, existingThenable]).then(
    value => { console.log("got a value", value); },
    error => { console.log("got an error", error); },
);

第一部分:下面的陈述是真的吗?
promise. resolve(innerPromise)将始终返回innerPromise作为值的已解析的promise,并且由于它始终解析,因此I将始终在. then block中结束。
如果尝试从传递给Promise.race的数组中删除existingValue,您将看到Promise.resolve不一定返回已解析的承诺;具体来说,当它传递一个promise或其他thenable时,它返回一个以相同方式解决的promise(尽管当传递相同类型的promise时,它实际上通过返回相同的promise对象来满足该义务)。所以不,这不是真的。我认为这也回答了第2部分。
另外,虽然你没有提起:我敢肯定,额外的.catch(reject)是无法访问/无用的,至少对于标准ES Promise实现是这样。

j2qf4p5b

j2qf4p5b2#

Promise.resolve(anotherPromise)将 * 总是 * 呈现anotherPromise的状态,因此如果anotherPromise被拒绝,则来自Promise.resolve()的那个也将被拒绝。或者如果anotherPromise被满足,则Promise.resolve()的那个也将用它的值来满足。

const rejectedPromise = Promise.reject("boom");

Promise.resolve(rejectedPromise)
  .then(result => console.log("success:", result))
  .catch(error => console.log("failure:", error));

参见the documentation on MDN for Promise.resolve()
至于 * 为什么 * 代码使用Promise.resolve()而不是直接使用

innerPromise
    .then(resolve, reject) 
    .catch(reject);

Promise.resolve()在输入不一定是promise时很有用,它可以将普通值转换为promise,或者将任意的thenable(可能是另一个promise实现)转换为vanilla JavaScript promise,从而允许以统一的方式处理结果。
也许这是一种防御性编码,或者只是允许调用race(asyncResult, 42),其意图尚不清楚。
executor函数中的resolvereject参数在重复调用时为noop。promise可以达到一个最终状态-在此之后调用resolve/reject无效。因此,从整个数组中,第一个离开挂起状态的promise将确定promise构造函数将被解析为什么。

const p1 = new Promise((resolve, reject) => {
  Promise.resolve("p1 success")
      .then(resolve, reject) 
      .catch(reject);
  Promise.reject("p1 failure")
      .then(resolve, reject) 
      .catch(reject);
});

const p2 = new Promise((resolve, reject) => {
  Promise.reject("p2 failure")
      .then(resolve, reject) 
      .catch(reject);
  Promise.resolve("p2 success")
      .then(resolve, reject) 
      .catch(reject);
});

const p3 = new Promise((resolve, reject) => {
  Promise.resolve("p3 hello")
      .then(resolve, reject) 
      .catch(reject);
  Promise.resolve("p3 world")
      .then(resolve, reject) 
      .catch(reject);
});

const p4 = new Promise((resolve, reject) => {
  Promise.reject("p4 foo")
      .then(resolve, reject) 
      .catch(reject);
  Promise.reject("p4 bar")
      .then(resolve, reject) 
      .catch(reject);
});

p1.then(console.log, console.error);
p2.then(console.log, console.error);
p3.then(console.log, console.error);
p4.then(console.log, console.error);

因此,通过循环并将相同的resolvereject附加到所有promise,race将只解析与第一个要解析的promise相同的结果。

返回值

一个承诺,它异步结算,最终状态为iterable中要结算的第一个承诺。换句话说,如果要结算的第一个承诺已履行,则它将履行。如果要结算的第一个承诺被拒绝,则返回承诺。如果传递的iterable为空,则返回的承诺将永远保持挂起状态。如果传递的iterable为非空,但不包含挂起的承诺,则返回的承诺仍异步(而不是同步)结算。
注意:iterablePromise.race()的输入,它与race()promisesArray匹配。
综上所述,以下构想似乎完全多余:

p
  .then(resolve, reject) 
  .catch(reject);

.then()的第二个参数是onRejected回调函数。因此,如果p被拒绝,.then()的第二个参数将用于处理该问题。额外的.catch()将处理来自.then()中的resolvereject的错误

Promise.resolve("foo")
  .then(
    result => { throw `Fulfilled with ${result}. Throwing after success.` }, 
    error => {throw `Fulfilled with ${error}. Throwing after error` }
  )
  .catch(errorFromThen => console.log(`Error in .catch() is: ${errorFromThen}`));

Promise.reject("bar")
  .then(
    result => { throw `Fulfilled with ${result}. Throwing after success.` }, 
    error => {throw `Fulfilled with ${error}. Throwing after error` }
  )
  .catch(errorFromThen => console.log(`Error in .catch() is: ${errorFromThen}`));

然而,executor函数中的resolvereject都不能在普通Promise构造函数中抛出/拒绝。

//more verbose onError and .catch() handlers in order to showcase what gts shown or not
const p = new Promise((resolve, reject) => {
  Promise.reject("hello")
    .then(
      resolve, 
      error => {
        console.log("inside the onReject in .then()", error);
        return reject(error);
      })
    .catch(error => {
          console.log("inside the .catch()", error);
          return reject(error);
      });
    
    Promise.reject("world")
      .then(
        resolve, 
        error => {
          console.log("inside the onReject in .then()", error);
          return reject(error);
        }
      )
      .catch(error => {
          console.log("inside the .catch()", error);
          return reject(error);
      });
});

p.then(console.log, console.error);

因此不使用额外的.catch()
总的来说,race()的行为类似于普通JavaScript Promise.race(),唯一的主要区别是Promise.race()接受任何可迭代对象,而race()只处理数组。

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

const array = [delay(300, "a"), delay(100, "b"), delay(200, "c")];
const iterable = array.values();

Promise.race(iterable)
  .then(result => console.log(`First to fulfil was ${result}`));
const race = function(promisesArray) {
  return new Promise((resolve, reject) => {
    promisesArray.forEach((innerPromise) => {
      Promise.resolve(innerPromise)
        .then(resolve, reject) 
        .catch(reject);
    });
  });
};

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

const array = [delay(300, "a"), delay(100, "b"), delay(200, "c")];
const iterable = array.values();

race(iterable)
  .then(result => console.log(`First to fulfil was ${result}`))
  .catch(console.error);

相关问题