版本3 实现Promise的then链的功能
我们先看一下es6给我们提供的Promise关于then链的特点
Promise的链式调用问题
1.如果then方法中(成功或者失败函数)返回的不是一个promise,会将这个值传递给外层下一次then的成功结果,如果没有返回值,默认返回undefined。
2.如果执行then方法中的方法(成功或者失败函数)出错了,抛出异常,会走到下一次then的失败中。
3.如果返回的是一个promise,如果返回的是一个成功的promise会走到下一次then成功的回调函数中,如果返回的是一个失败的promise会走到下一次then失败的回调函数中。会用这个promise的结果做为下一次then的成功或者失败。
总结:Promise 什么时候当前then走完了会走到下一次then的失败中去
1) 出错或者手动抛出异常会走失败
2) 返回的 Promise 出错
除了以上两点之外都走到下一次then的成功中去。
then() 方法为什么可以链式调用,因为每次调用then都返回一个新的 Promise
,
catch 就是then的别名,没有成功的回调只有失败的回调(错误处理: 找最近的优先处理,处理不了找下一层)
问题1:如果我有10个then,第一个出错了,会一直走剩下的9个吗?
答:那就看你有没有捕获异常,如果你有捕获异常,会接着往下走,如果你一个捕获异常都没有会跳过剩下的9个then,找到最后面的,如果还没有捕获异常就报错说你没有处理异常。就是一句话:你错误处理了接着走正常的,错误没有处理则报错。
回顾了es6提供的Promise给我们提供的then链的特点之后,我们实现一个自己的Promise的then链功能、
promise.js文件代码
const Promise = require('./3-promise.js')
const p = new Promise((resolve, reject) => {
console.log('默认执行');
setTimeout(() => {
reject('失败了')
}, 2000)
// resolve('成功了')
})
p.then((value) => {
console.log('s1', value);
return 100;
}, (reason) => {
console.log('f1', reason);
return 200;
}).then((value) => {
console.log('s2', value);
}, (reason) => {
console.log('f2', reason);
})
3-promise.js文件代码(关键)
// 新增Promise then链的功能
const STATUS = {
PENDING: 'PENDING',
FULFILLED: 'FULFILLED',
REJECTED: 'REJECTED'
}
class Promise {
constructor(executor) { // constructor是类的构造函数
this.status = STATUS.PENDING;
this.value = null;
this.reason = null;
this.onResolvedCallbacks = []; // 存放成功的回调的
this.onRejectedCallbacks = []; // 存放失败的回调的
const resolve = (value) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn()) // 发布
}
}
const reject = (reason) => {
if (this.status === STATUS.PENDING) {
this.status = STATUS.REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn()) // 发布
}
}
try {
executor(resolve, reject);
} catch(error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
let promise2 = new Promise((resolve, reject) => {
if (this.status === STATUS.FULFILLED) {
try {
let x = onFulfilled(this.value);
resolve(x);
} catch(error) {
reject(error);
}
}
if (this.status === STATUS.REJECTED) {
try {
let x = onRejected(this.reason);
resolve(x);
} catch(error) {
reject(error);
}
}
if (this.status === STATUS.PENDING) {
this.onResolvedCallbacks.push(() => {
try {
let x = onFulfilled(this.value)
resolve(x)
} catch(error) {
reject(error)
}
})
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.reason)
resolve(x)
} catch(error) {
reject(error)
}
})
}
})
return promise2
}
}
module.exports = Promise;