promise原理 及 手动实现(符合Promse/A+规范 — 完整注释)
promise 解决的问题
- 回调嵌套/回调地狱
- 多重异步处理错误捕获不方便
- 多重异步同步处理的问题 异步并发问题
promise 定义
- Promise是一个类 默认浏览器、高版本(ie8以上)、node都自带了,图个没有可以引入es6-promise
- Promise符合Promise/A+规范
- Promose 有三个状态 等待(‘pending’) 成功(’‘success’’) 失败(‘failed’)
- 只有在等待状态是才可以修改状态,并且状态变化后不能再次修改状态
- Promise的实例上有一个then函数,then可以查看promise实例的状态
promise 的then方法
- then方法可以传递两个方法onFulfilled, onRejected,分别对于成功状态和失败状态时的回调
- 处理异步时,如果同一个primise实例then多次时,当promise实例状态改变时,会分别依次执行每一个then方法对应状态的回调函数
- promise的then方法可以链式调用,promise的链式调用不是通过返回当前实例的方式
- 因为当前实例无法多次改变状态
- promise每一次then后都会返回一个新的promise实例,并且将前一次promise的执行结果传给当前then的onFulfilled, onRejected函数
- promise的执行结果有2种状态 普通值(只要不是promise就是普通值) 和 非普通值(promise实例)
- 链式调用的onRejected函数只有两种情况会执行
- 1)前一次then返回promise && promise的状态是失败,
- 2)前一次then报错
- 当前一次then返回一个promise && promise的状态是成功 或者 返回一个普通值时执行 onFulfilled函数
- onFulfilled函数会接收一个参数data,data是当前实例resolve接收的参数或者前一个then的执行结果
- onRejected函数会接收一个参数err,err是当前实例reject接收的参数或者前一个then的执行结果或者报错信息
- 当then中没有传onFulfilled, onRejected参数或者onFulfilled, onRejected参数不是函数类型是,会将data和err向下一个then传递
实现自己的promise
// 预存Promise的三种状态
const PENDING = 'pending',
SUCCESS = 'success',
FAILED = 'failed';
// 判断当前then的onFulfilled, onRejected函数执行结果是不是promise
const resolvePromise = (newPromise, x, res, rej) => {
// 首先 当前then的onFulfilled, onRejected函数执行结果不可以是当前then返回的promise,否则就是当前then返回的promise等待自己的执行结果,代码就会停止 所以者了报一个类型错误
if (newPromise === x) rej(new TypeError('Chaining cycle detected for promise #<Promise>'));
let called; // 创建一个flag保证当前then返回的promise如果不是自己的promise时不会多次改变状态
// 只有x是函数的时候才会有then的方法
if (typeof x === 'function' || (typeof x === 'object' && x !== null)) {
try { // 拿到他很方法,防止取值then是报错,如果报错直接执行rej方法
let then = x.then;
if (typeof then === 'function') { // 如过then是一个函数那么我们就认为当前的x是一个promise
then.call(x, // 这里是防止多次取值then报错
y => { // 当x执行成功函数时,也有可能返回一个promise所以这里递归判断返回值直到返回值是普通值或者非普通值执行失败函数
if (called) return; // 创建一个flag保证当前then返回的promise如果不是自己的promise时不会多次改变状态
called = true;
resolvePromise(newPromise, y, res, rej)
},
e => { // 当x执行失败函数时
if (called) return; // 创建一个flag保证当前then返回的promise如果不是自己的promise时不会多次改变状态
called = true;
rej(e)
}
);
} else { // 如果then不是函数那么我们就认为x不是promise
res(x)
}
} catch (error) {
if (called) return; // 创建一个flag保证当前then返回的promise如果不是自己的promise时不会多次改变状态
called = true;
rej(x) // 报错时直接执行失败函数
}
} else {
res(x)
}
}
// 创建一个自己的Promise类
class Promise {
constructor(executor) { // executor会在实例化是立即执行
this.status = PENDING; // Promise的状态默认是等待状态
this.value = null; // Promise成功时的返回值
this.err = null; // Promise失败的返回值
this.onFCB = []; // 当一个Promise实例多次then是存放对应成功状态的回调函数的数组
this.onRCB = []; // 当一个Promise实例多次then是存放对应失败状态的回调函数的数组
let resolve = value => { // Promise改变状态为成功的函数
if (this.status === PENDING) { // 只有当Promise状态为等待时才可以改变状态
this.status = SUCCESS; // 将Promise状态改为成功
this.value = value; // 将执行成功时传递的返回值存下
this.onFCB.forEach(fn => fn(this.value)); // 依次执行当前实例所有then中的onFulfilled
}
}
let reject = err => { // Promise改变状态为失败的函数
if (this.status === PENDING) { // 只有当Promise状态为等待时才可以改变状态
this.status = FAILED; // 将Promise状态改为失败
this.err = err; // 将执行失败时传递的返回值存下
this.onRCB.forEach(fn => fn(this.err)); // 依次执行当前实例所有then中的onRejected
}
}
// 实例化时立即执行executor执行器
try { // 如果执行executor是报错则直接执行改变Promise失败的方法并将报错信息作为当前实例的返回值
executor(resolve, reject);
} catch (error) {
reject(error) // 报错时直接执行失败函数
}
}
then(onF, onR) { // 执行then时传递两个函数onFulfilled, onRejected,分别对于改变成功状态和改变失败状态的回调函数
// 如果onFulfilled, onRejected不是函数 那么会将当前实例的成功和失败的返回值作为参数直接传递给对应的下一个then的onFulfilled, onRejected函数 --- then值的穿透
onF = typeof onF === 'function' ? onF : val => val;
onR = typeof onR === 'function' ? onR : err => {
throw err; Î
}
// 重新new一个promise实例,并作为当前then的返回值return
let newPromise;
newPromise = new Promise((res, rej) => {
switch (this.status) {
case SUCCESS: // 如果当前实例状态为成功时
setTimeout(() => {
try { // 如果前一个then返回的promise报错则直接执行当前then返回值的失败方法
let x = onF(this.value); // 拿到当前then的onFulfilled的结果
resolvePromise(newPromise, x, res, rej); // 判断当前then的执行结果是普通值还是非普通值,如果是非普通值的失败或者报错则执行当前then返回值的rej方法,否则执行res方法
} catch (error) {
rej(error) // 报错时直接执行失败函数
}
})
return;
case FAILED:
setTimeout(() => {
try { // 如果前一个then返回的promise报错则直接执行当前then返回值的失败方法
let x = onR(this.err); // 拿到当前then的 onRejected的结果
resolvePromise(newPromise, x, res, rej); // 判断当前then的执行结果是普通值还是非普通值,如果是非普通值的失败或者报错则执行当前then返回值的rej方法,否则执行res方法
} catch (error) {
rej(error) // 报错时直接执行失败函数
}
})
return;
case PENDING:
this.onFCB.push(() => {
setTimeout(() => {
try { // 如果前一个then返回的promise报错则直接执行当前then返回值的失败方法
let x = onF(this.value); // 拿到当前then的onFulfilled的结果
resolvePromise(newPromise, x, res, rej); // 判断当前then的执行结果是普通值还是非普通值,如果是非普通值的失败或者报错则执行当前then返回值的rej方法,否则执行res方法
} catch (error) {
rej(error) // 报错时直接执行失败函数
}
})
})
this.onRCB.push(() => {
setTimeout(() => {
try { // 如果前一个then返回的promise报错则直接执行当前then返回值的失败方法
let x = onR(this.err); // 拿到当前then的 onRejected的结果
resolvePromise(newPromise, x, res, rej); // 判断当前then的执行结果是普通值还是非普通值,如果是非普通值的失败或者报错则执行当前then返回值的rej方法,否则执行res方法
} catch (error) {
rej(error) // 报错时直接执行失败函数
}
})
})
return;
default:
return;
}
})
return newPromise; // 返回新的promise实例实现链式调用
}
}