任务:
如果Mike能够打扫房间,那么他去踢足球。在足球比赛中,如果他进球了,作为奖励他有机会去参观音乐会。如果他没有进球,那么他清理他的狗。如果他无法打扫房间,那么他洗衣服。如果他也不能完成洗衣,那么他必须清理他的狗。但如果他能完成洗衣,那么他去看音乐会。
解决方案:
const cleanRoom = (resolve, reject) => {
let num = Math.random();
if (num >= .5) {
resolve(num); //房间已打扫
} else {
reject(new Error(num)); //房间未打扫
}
}
const roomCleaningPromise = new Promise(cleanRoom);
roomCleaningPromise.then(function goFootballAfterCleaning(resolveValue) {
console.log(`已打扫房间,现在去踢足球:${resolveValue}`);
return new Promise(function makeGoal(resolve, reject) {
let number = Math.random();
if (number >= .5) { //去音乐会
resolve(number);
} else {
reject(number); //清理狗
}
})
}).then(function goConcertAfterGoal(resolveValue) {
console.log(`已打扫房间,去踢足球并进球了!现在去音乐演唱会:${resolveValue}`);
}).catch(function cleanDogAfterlosing(errorValue) {
console.log(`已打扫房间,去踢足球但没进球,所以清理狗:${errorValue}`);
})
roomCleaningPromise.catch(function goLaundaryAfterNoCleaning(errorValue) {
console.log(`未打扫房间,所以去洗衣服:${errorValue}`);
return new Promise(function doLaundary(resolve, reject) {
let number_2 = Math.random();
if (number_2 >= .5) { //去音乐会
resolve(number_2);
} else {
reject(number_2); //清理狗
}
})
}).then(function goConcertAfterLaundary(resolveValue) {
console.log(`未打扫房间,去洗衣服并完成了,现在去音乐演唱会:${resolveValue}`);
}).catch(function cleanDogAfterNoLaundary(errorValue){
console.log(`未打扫房间,去洗衣服但未完成,所以清理狗:${errorValue}`);
})
输出:
未打扫房间,所以去洗衣服:Error: 0.10282616920143206
已打扫房间,去踢足球但没进球,所以清理狗:Error: 0.10282616920143206
未打扫房间,去洗衣服但未完成,所以清理狗:0.3140749736813231
疑问:
现在我的问题是,如果房间未打扫,为什么打印出“已打扫房间……”?如果初始Promise被拒绝,控制权应该转到代码的第二个.catch()
,然后如果第二个Promise也被拒绝,控制权应该只转到最后一个.catch()
。为什么没有发生这种情况?
期望输出:
可能的一个期望输出是这样的:
未打扫房间,所以去洗衣服:Error: 0.10282616920143206
未打扫房间,去洗衣服但未完成,所以清理狗:0.3140749736813231
推断:
推断1:我现在明白,如果一个.then()
和一个.catch()
附加到同一个Promise(p1),即使它们都使用“new”来创建Promise,它们实际上指向相同的Promise实例。因此在我的代码中,当goLaundryAfterNoCleaning .catch()
块返回一个被拒绝的Promise时,它找到的是上面而不是下面的第一个.catch()
,因为从技术上讲,如果这个被拒绝的Promise与由goFootballAfterCleaning .then()
返回的Promise是同一个实例,那么第一个.catch()
应该是上面的那个。
疑问:
- 为什么会这样?为什么由
.then()
和.catch()
返回的Promise都指向同一个实例?
- 如何修改我的代码以按照预期的方式完成任务?
推断2:在goLaundryAfterNoCleaning .catch()
返回一个被拒绝的Promise后,控制权转移到第一个.catch()
(C1)块。现在,这个.catch()
(C1)也“隐式”地返回了一个被拒绝的Promise,因此代码流继续到链中的下一个.catch()
(代码的最后一.catch()
),尽管根据预期任务,它本应在运行C1后停止。
疑问:
如何解决这个问题并在此处停止代码流程?
参考:
上述任务和代码基于Praveen Gaur在Medium上的文章《JavaScript Promises》