在 JavaScript 中实现 Promise Chaining 时出现意外输出

问题描述 投票:0回答:1

我有一个如下的任务,我必须在 JavaScript 中使用 Promise Chaining 来解决它,并且我得到了一些意想不到的输出 -:

任务:

如果迈克能够打扫房间,那么他就会去踢足球。 在足球比赛中,如果他进球,那么作为奖励,他将有机会参观音乐会。如果他没有进球,他就会清理他的狗。 如果他不能打扫房间,他就会洗衣服。 如果他也无法洗完衣服,那么他就必须清理他的狗。 但如果他能洗干净衣服,他就会去听音乐会。

解决方案:

const cleanRoom = (resolve, reject) => {
    let num = Math.random();
    if (num >= .5) { 
      resolve(num); //room cleaned
    } else {
      reject(new Error(num)); //room not cleaned
    }
  }
const roomCleaningPromise = new Promise(cleanRoom);

roomCleaningPromise.then(function goFootballAfterCleaning(resolveValue) {
  console.log(`Room was cleaned so going to play Football -: ${resolveValue}`);
  return new Promise(function makeGoal(resolve, reject) {
    let number = Math.random();
    if (number >= .5) { //go to concert
      resolve(number);
    } else {
      reject(number); //dog cleaning
    }
  }) 
}).then(function goConcertAfterGoal(resolveValue) {
  console.log(`Room was cleaned so went to play Football and made a goal!! Now Going to Music concert -: ${resolveValue}`);
}).catch(function cleanDogAfterlosing(errorValue) {
  console.log(`Room was cleaned so went to play Football but couldn't make a goal so Cleaning the dog -: ${errorValue}`);
})
  
roomCleaningPromise.catch(function goLaundaryAfterNoCleaning(errorValue) {
  console.log(`Room was not cleaned so going to do Laundry -: ${errorValue}`);
  return new Promise(function doLaundary(resolve, reject) {
    let number_2 = Math.random();
    if (number_2 >= .5) { //go to concert
      resolve(number_2);
    } else {
      reject(number_2); //dog cleaning
    }
  })
}).then(function goConcertAfterLaundary(resolveValue) {
  console.log(`Room was not cleaned so went to do Laundry, which I completed so now going to Music Concert -: ${resolveValue}`);
}).catch(function cleanDogAfterNoLaundary(errorValue){
  console.log(`Room was not cleaned so went to do Laundry, which I didn't complete so cleaning the dog -: ${errorValue}`);
})

输出:

Room was not cleaned so going to do Laundry -: Error: 0.10282616920143206
Room was cleaned so went to play Football but couldn't make a goal so Cleaning the dog -: Error: 0.10282616920143206
Room was not cleaned so went to do Laundry, which I didn't complete so cleaning the dog -: 0.3140749736813231

疑问:

现在我的问题是,如果房间没有打扫那么为什么会打印“房间已打扫......”?如果最初的 Promise 被拒绝,那么控件应该转到代码的第二个 .catch() ,然后如果第二个 Promise 也被拒绝,那么控件应该转到最后一个 .catch() ,就是这样。为什么这没有发生?

预期输出:

其中一个可能的预期输出将类似于-:

Room was not cleaned so going to do Laundry -: Error: 0.10282616920143206
Room was not cleaned so went to do Laundry, which I didn't complete so cleaning the dog -: 0.3140749736813231

参考:

上述任务和代码基于 Praveen Gaur 的 “JavaScript Promises” Medium 文章。

javascript asynchronous ecmascript-6 promise callback
1个回答
0
投票

如果您有一个被拒绝的 Promise,并且将单参数

then
子句链接到它,则这些
then
子句返回的 Promise 将以与原始方式相同的方式被拒绝。这是因为
then
的定义中的规则:

如果它 [onFulfilled] 不是一个函数,它会在内部被替换为一个恒等函数 (

(x) => x
),该函数只是向前传递履行值。

如果它 [onRejected] 不是一个函数,它会在内部被替换为抛出函数 (

(x) => { throw x; }
),该函数会抛出收到的拒绝原因。

在这里,你的

cleanRoom
被拒绝了;您在没有
then
处理程序的情况下链接了两个
onRejected
调用,因此当您到达
catch
子句时,您的 Promise 仍以其初始状态被拒绝。您读到的文章没有充分描述这种情况。

const roomCleaningPromise = Promise.reject(new Error("original failure"));

roomCleaningPromise.then(function goFootballAfterCleaning(resolveValue) {
  console.log("this doesn't run, roomCleaningPromise failed");
}).then(function goConcertAfterGoal(resolveValue) {
  console.log("this doesn't run, roomCleaningPromise failed");
}).catch(function cleanDogAfterLosing(errorValue) {
  console.log(`Catch #1, value: ${errorValue}`);
})
  
roomCleaningPromise.catch(function goLaundryAfterNoCleaning(errorValue) {
  console.log(`Catch #2, value: ${errorValue}`);
  return new Promise(function doLaundry(resolve, reject) {
    let number_2 = Math.random();
    if (number_2 >= .5) { //go to concert
      resolve(number_2);
    } else {
      reject(number_2); //dog cleaning
    }
  })
}).then(function goConcertAfterLaundary(resolveValue) {
  console.log(`Laundry + concert: ${resolveValue}`);
}).catch(function cleanDogAfterNoLaundary(errorValue){
  console.log(`Laundry + dog: ${errorValue}`);
})

传播错误的能力应该被视为 Promise 的一项功能,并且近似于以异步方式使用

try
/
catch

function main() {
  try {
    a();
  } catch(e) {
    console.log(e);
  }
}

function a() {
  b();
  console.log("this doesn't happen because b throws");
}

function b() {
  throw new Error("this is logged by main despite not being handled in a");
}
© www.soinside.com 2019 - 2024. All rights reserved.