前言:该内容仅为本人的学习笔记,如果有出错的地方欢迎指正,感谢
Promise源码
1.核心实现原理
- Promise就是一个类 在执行这个类的时候需要传递一个执行器进去,执行器会立即执行
- Promise中由三个状态分别的fulfilled、、pending,一旦状态确定了就不可改变
- resolve(fulfilled)和reject(rejected)函数式用来更改状态
- then方法的内部做的事情就是判断状态,并调用对应函数,且这个给方法在原型对象上
- then成功过回调由一个参数表示成功的值,失败有一个值表示失败后的原因
const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled'//成功
const REJECTED = 'rejected' //失败
class MyPromise{
constructor(executor){
executor(this.resolve,this.reject)
}
status = PENDING;
//成功之后的值
value = undefined;
//失败后的原因
reason =undefined;
resolve = value =>{
//如果状态不是等待,阻止程序向下执行
if(this.status !== PENDING) return;
//将状态更改为成功
this.status = FULFILLED
//保存成功之后的值
this.value =value
}
reject = reason => {
//如果状态不是等待,阻止程序向下执行
if(this.status !== PENDING) return;
//将状态更改为失败
this.status = REJECTED
this.reason =reason
}
then(successCallback,failCallback){
//判断状态
if(this.status === FULFILLED){
successCallback(this.value)
}
else if (this.status === REJECTED) {
failCallback(this.reason)
}
}
2.在promise中加入异步执行
- 如果在执行过程中有异步任务的化,需要等待这个异步走完才执行resolve和reject的回调,此时promise还是pending态的,所有要加入pending态的处理
class MyPromise{
//...略...
//成功之后执行的回调
successCallback = undefined;
//失败状态的回调
failCallback = undefined ;
resolve = value =>{
//...略...
//写了个短路运算
this.successCallback && this.successCallback(this.value)
}
reject = reason => {
//...略...
this.failCallback && this.failCallback(this.reason)
}
then(successCallback,failCallback){
//...略...
else{
//等待态
this.successCallback = successCallback;
this.failCallback = failCallback
}
}
}
3.then方法的多次执行
当then多次调用的时候需要对异步情况此做特殊处理
//将存放回调的字面量改成数组
//成功之后执行的回调
successCallback = [];
//失败状态的回调
failCallback = [] ;
//成功态的回调改成执行数据对第一个,并切出来,根据数组长度判断
// this.successCallback && this.successCallback(this.value)
while(this.successCallback.length){
this.successCallback.shift()(this.value)
}
// this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length){
this.failCallback.shift()(this.reason)
}
//等待态,把回调函添加都数组中
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
4.then方法实现链式调用
- 实现then方法的链式调用
- then方法在promise里面的,我们要实现then,最基本就算是返回一个promise对象
- 同时then内部代码式同步执行,所以把之前的代码,传入到new promise的执行器中
- 把上一个then方法的返回值传到下
- 调用执行器内的resolve,把回调函数的值传到返回的promise对象中
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve,reject ) => {
if (this.status === FULFILLED) {
let x = successCallback(this.value)
resolve(x)
}
else if (this.status === REJECTED) {
failCallback(this.reason)
} else {
this.successCallback.push(successCallback);
this.failCallback.push(failCallback);
}
})
//判断状态
// if(this.status === FULFILLED){
// successCallback(this.value)
// }
// else if (this.status === REJECTED) {
// failCallback(this.reason)
// }else{
// //等待态
// this.successCallback.push(successCallback);
// this.failCallback.push(failCallback);
// }
return promise2
}
- 链式调用深入(回顾链式调用实际使用)
- 判断x的值式普通值还是promise对象
- 如果是普通值直接调用resolve传出去
- 如果是promise对象,查看promise对象的返回结果
- 在根据promise对象的返回结果,决定调用resolve还是调用reject
//把then方法的返回值传到一个处理函数中
let x = successCallback(this.value)
resolvePromise(x,resolve,reject)
function resolvePromise(x,resolve,reject){
//判断是不是Mypromsier的实例化对象
if(x instanceof MyPromise){
// 如果返回的promise对象的话我们就用then的方法去判断他有有没有状态改变
//有的话执行就调用resolve,reject把值传递下去
// x.then(value => resolve(value),reason => reject(reson))
// 优化写法
x.then(resolve,reject)
}
else{
resolve(x)
}
}
5.then方法链式调用识别Promiese对象自返回
- promise不允许自返回
- 在处理返回值函数中传入新的promise和返回值做未必
function resolvePromise(promise2, x, resolve, reject) {
//把promise2作为参数传入进来去判断
if (promise2 == x) {
return reject(new TypeError('不能自返回'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
else {
resolve(x)
- 注意的是这列要异步处理不然的话的这个promise2是拿不到,因为是要等代码执行玩才赋值给这个promise2,所以让他异步才能拿到
if (this.status === FULFILLED) {
setTimeout(() => {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
},0)
}
6.捕获错误接then链式调用其他代码的补充
- 在promise执行的函数中的错误捕获
constructor(executor) {
try{
executor(this.resolve, this.reject)
}
catch(e){
this.reject(e)
}
}
- then方法回调函数执行代码错误捕获
if (this.status === FULFILLED) {
setTimeout(() => {
try{
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
}
catch(e){
//当执行错误的时候,就把错误信息传递给出去
reject(e)
}
},0)
}
else if (this.status === REJECTED) {
setTimeout(() => {
try{
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, re
}
catch(e){
reject(e)
}
},0)
}
- pending时候then函数执行代码错误捕获
//当上一个promise状态未改变时候是异步回调函数
this.successCallback.shift()()
this.failCallback.shift()()
else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
}
);
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
});
}
7.then方法的参数是可选参数
- then方法内可以不传递参数。就把原来的值传递和状态
successCallback = successCallback? successCallback : value => value
failCallback = failCallback? failCallback : reason => {throw reason} //这里需要抛出错误,不然又回到resolve
8.all方法实现
- promise.all(),用来解决异步代码的并发问题,它允许我们根据异步代码的调用顺序去得到。
promise.all(['a','b',p1(),p2(),'c'])=> result --['a','b',p1(),p2(),'c']- promise.all返回值也是一个promise对象
- 如果all方法都是成功,则返回是成功状态,有一个失败则返回失败状态
- all是一个静态方法
//根据promise的调用,Promise.all()是一个静态方法
static all(array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
// 需要在内部定义这个添加结果的方法,不然拿不到的resolve
function addData(key, value) {
result[key] = value
// 定义一个计数器,当执行这个addData的时候就加以,就可以避免异步操作的返回空值
index++;
if (index === array.length) {
resolve(result)
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
//promise对象的话就执行,参考类似调用then的链式调用
//如果是promise是成功态的就把值押入到result数组中
//失败态就直接抛出
current.then(value => addData(i, value), reject)
}
else {
//普通值
addData(i, array[i]);
}
// resolve(result)
}
})
}
9.resolve方法实现
- resolve(),如果是传递一个值,就返回一个promise对象,并把值传递下去
- 如果是promsie对象,就把这个promise原封不动返回出去
- resolve(),方法的作用就是把传递过去的值转化成一个promise对象
static resolve(value) {
if(value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value))
}
10.finally方法实现
- finally方法无论,promise对象是成功还是失败,里面对回调函数还是会被执行一次
- finally方法之后调用then方法能够获取当前promise对象的最终返回值
- 但是要注意调用的then方法是要等待这个finally执行完毕后在执行
finally(callback){
// then方法是可以获取当前的状态值,这样可以把当前的壮态值传递给下一个then跟里面内容无关的
return this.then( value => {
// callback()
// return value
//这一步可以解决finlly的异步问题,到callback执行完成后再往下走
//通过调用resolve方法把传递值转化未promise对象,实现异步处理
return MyPromise.resolve(callback()).then(()=>{value})
}, reason => {
// callback()
// throw reason
return MyPromise.resolve(callback()).then(()=>{throw reason})
})
}
11catch方法实现
- catch方法就是用链式调用处理错误方法
catch (failCallback){
return this.then(undefined,failCallback)
}
12.完整代码
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve, this.reject)
}
catch (e) {
this.reject(e)
}
}
status = PENDING;
value = undefined;
reason = undefined;
successCallback = [];
failCallback = [];
resolve = value => {
if (this.status !== PENDING) return;
this.status = FULFILLED
this.value = value
while (this.successCallback.length) {
this.successCallback.shift()()
}
}
reject = reason => {
if (this.status !== PENDING) return;
this.status = REJECTED
this.reason = reason
while (this.failCallback.length) {
this.failCallback.shift()()
}
}
then(successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
}
else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
}
else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
}
);
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
resolvePromise(promise2, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0)
});
}
})
return promise2
}
finally(callback){
return this.then( value => {
return MyPromise.resolve(callback()).then(()=>{value})
}, reason => {
return MyPromise.resolve(callback()).then(()=>{throw reason})
})
}
catch (failCallback){
return this.then(undefined,failCallback)
}
static all(array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
index++;
if (index === array.length) {
resolve(result)
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i];
if (current instanceof MyPromise) {
current.then(value => addData(i, value), reject)
}
else {
addData(i, array[i]);
}
}
})
}
static resolve(value) {
if(value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value))
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 == x) {
return reject(new TypeError('不能自返回'))
}
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
else {
resolve(x)
}
}