学习笔记-Promise

315 阅读7分钟

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理且更强大。它最早由社区提出并实现,ES6将其写进了语言标准,统一了用法,并原生提供了Promise对象。

Promise使用

const p = new Promise((resolve, reject) => {
    console.log('立即执行');
    resolve('成功');
});

p.then(res => {
    console.log('res', res);
})
  • 1 Promise 是一个构造函数
  • 2 new Promise的时候传入一个执行函数,且是立即执行的
  • 3 执行函数接收两个参数resolve函数, reject函数,且可以接受参数
  • 4 Promise实例上有个then的方法,then方法接收两个参数
  • 5 resolve函数, reject函数是内部函数

基本结构

class basicPromise {
    constructor(excutor) {
        let resolve = (value) => {
            console.log(value);
        }
        let reject = (reason) => {
            console.log(reason);
        }
        try {
            excutor(resolve, reject)
        } catch (error) {
            throw error;
        }
    }
    then(fn1, fn2) {

    }
}
let bp = new basicPromise((resolve, reject) => {
    resolve('成功');
})

bp.then(res => {
    console.log('res--',res);
})

Promise 的状态

一个 promise 所处的状态必须为以下三者之一:待定(pending),兑现(fulfilled,有时候也称为 “解决”,resolved),拒绝(rejected)

  1. 当处于待定状态时:

    1. 可以流转为代表成功的兑现状态,或者代表失败的拒绝状态。
  2. 当处于兑现状态时:

    1. 不可流转到其它任何状态
    2. 必须拥有一个不可变的终值
  3. 当处于拒绝状态时:

    1. 不可流转到其它任何状态

    2. 必须拥有一个不可变的拒因

 /*
    resolve()   promise的状态 pending  -->   fulfilled;
    reject()  promise的状态pending  -->   rejected
  */
 const PENDING = 'pending';
 const FULFILLED = 'fulfilled';
 const REJECTED = 'rejected';
 class basicPromise {
     constructor(excutor) {
        this.state = PENDING;
         let resolve = (value) => {
            if(this.state === PENDING) {
                this.state = FULFILLED;
                console.log(value);
            }
         }
         let reject = (reason) => {
            if (this.state === PENDING) {
                this.state = REJECTED;
                console.log(reason);
            }
             
         }
         try {
             excutor(resolve, reject)
         } catch (error) {
             throw error;
         }
     }
     then(fn1, fn2) {

     }
 }
 let p1 = new basicPromise((resolve, reject) => {
     resolve('成功');
 })

 p1.then(res => {
     console.log('res--', res);
 })

then 方法

一个 promise 必须提供一个 then 方法以访问其当前值或者终值或者拒因。 promise.then(onFulfilled, onRejected)

  1. onFulfilled 和 onRejected 都是可选参数:

    如果 onFulfilled 不是函数,必须将其忽略

    如果 onRejected 不是函数,必须将其忽略

  2. 如果 onFulfilled 是函数:

    当 promise 解决后其必须被调用,其第一个参数为 promise 的终值

    在 promise 解决前其不可被调用

    其调用次数不可超过一次

  3. 如果 onRejected 是函数:

    当 promise 拒绝后其必须被调用,其第一个参数为 promise 的拒因

    在 promise 拒绝前其不可被调用

    其调用次数不可超过一次

  4. 调用时机

onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用

  1. 调用要求

onFulfilled 和 onRejected 必须被作为函数调用(换句话说就是:没有 this 值)

执行函数为异步函数(同步忽略)
 const PENDING = 'pending';
 const FULFILLED = 'fulfilled';
 const REJECTED = 'rejected';

 class basicPromise {
     constructor(excutor) {
         this.state = PENDING; // 状态
         this.value = undefined; // 成功返回
         this.reason = undefined; // 失败返回

         //  异步函数存储
         this.onFulfilledCallback = undefined;
         this.onRejectedCallback = undefined;

         let resolve = (value) => {
             if (this.state === PENDING) {
                 this.state = FULFILLED;
                 this.value = value;
                 this.onFulfilledCallback && this.onFulfilledCallback(value)
             }
         }

         let reject = (reason) => {
             if (this.state === PENDING) {
                 this.state = REJECTED;
                 this.reason = reason;
                 this.onRejectedCallback && this.onFulfilledCallback(reason)
             }

         }

         try {
             excutor(resolve, reject)
         } catch (error) {
             throw error;
         }
     }

     then(onFulfilled, onRejected) {
         if (this.state === FULFILLED) {
             typeof onFulfilled === 'function' && setTimeout(() => {
                 onFulfilled(this.value);
             }, 0)
         } else if (this.state === REJECTED) {
             typeof onRejected === 'function' && setTimeout(() => {
                 onRejected(this.reason);
             }, 0)
         } else {
             // 执行函数为异步函数
             if (typeof onFulfilled === 'function') {
                 this.onFulfilledCallback = (value) => setTimeout(() => {
                     onFulfilled(value)
                 }, 0)
             }
             if (typeof onRejected === 'function') {
                this.onRejectedCallback = (reason) => setTimeout(() => {
                    onRejected(reason)
                }, 0)
            }
         }
     }
 }

 let p1 = new basicPromise((resolve, reject) => {
     setTimeout(() => {
         console.log('立即执行');
         //  resolve('成功');
         reject('失败');
     }, 1000)

 })

 p1.then(res => {
     console.log('res--', res);
 }, reason => {
     console.log('reason', reason);
 })
 1 执行函数为同步函数的时候,
     在 const p = new Promise(executor) 时,执行函数会立即执行,且是同步的,
     那么resolve函数也是同步执行,此时promise的状态已经改变了,
     value也拿到了,然后再执行p.then(onFulfilled, onRejected),
     此时便可以直接判断promise的状态来执行的函数
 2 执行函数为异步函数的时候
     在 const p = new Promise(executor) 时,执行函数立即执行,
     但是resolve函数是异步执行的,此时的promise的状态仍是待定的,
     value值仍为undifined,然后再同步执行p.then(onFulfilled, onRejected),
     此时可以将onFulfilled, onRejected函数保存下来(class中直接保存到this),
     等到异步执行resolve函数时,在resolve函数中执行onFulfilled并传参即可,
     同理reject函数中执行onRejected

then函数多次被调用

 const PENDING = 'pending';
 const FULFILLED = 'fulfilled';
 const REJECTED = 'rejected';

 class basicPromise {
     constructor(excutor) {
         this.state = PENDING; // 状态
         this.value = undefined; // 成功返回
         this.reason = undefined; // 失败返回

         //  异步函数存储
         this.onFulfilledCallbacks = []; //数组形式
         this.onRejectedCallbacks = [];

         let resolve = (value) => {
             if (this.state === PENDING) {
                 this.state = FULFILLED;
                 this.value = value;
                 this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
                     resolve(value)
                 })
             }
         }

         let reject = (reason) => {
             if (this.state === PENDING) {
                 this.state = REJECTED;
                 this.reason = reason;
                 this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
                     reject(reason)
                 })
             }

         }

         try {
             excutor(resolve, reject)
         } catch (error) {
             throw error;
         }
     }

     then(onFulfilled, onRejected) {
         if (this.state === FULFILLED) {
             typeof onFulfilled === 'function' && setTimeout(() => {
                 onFulfilled(this.value);
             }, 0)
         } else if (this.state === REJECTED) {
             typeof onRejected === 'function' && setTimeout(() => {
                 onRejected(this.reason);
             }, 0)
         } else {
             // 执行函数为异步函数
             if (typeof onFulfilled === 'function') {
                 this.onFulfilledCallbacks.push((value) => setTimeout(() => {
                     onFulfilled(value)
                 }, 0))
             }
             if (typeof onRejected === 'function') {
                 this.onRejectedCallbacks.push((reason) => setTimeout(() => {
                     onRejected(reason)
                 }, 0))
             }
         }
     }
 }
 let p1 = new basicPromise((resolve, reject) => {
     setTimeout(() => {
         console.log('立即执行');
         //  resolve('成功');
         reject('失败');
     }, 1000)

 })

 p1.then(res => {
     console.log('res--', res);
 }, reason => {
     console.log('reason', reason);
 })

 p1.then(res => {
     console.log('res--', res);
 }, reason => {
     console.log('reason', reason);
 })

 p1.then(res => {
     console.log('res--', res);
 }, reason => {
     console.log('reason', reason);
 })

then方法必须返回一个promise对象

  1. 如果 onFulfilled 或者 onRejected 为函数且返回一个值 x ,则运行 Promise 解决过程:[[Resolve]](promise2, x)
  2. 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝并返回拒因 e
  3. 如果 onFulfilled 不是函数且 promise1 已解决, promise2 必须解决并返回与 promise1 相同的值
  4. 如果 onRejected 不是函数且 promise1 已拒绝, promise2 必须拒绝并返回与 promise1 相同的拒因
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function resolvePromise(promise, x) {

}

class basicPromise {
    constructor(excutor) {
        this.state = PENDING; // 状态
        this.value = undefined; // 成功返回
        this.reason = undefined; // 失败返回

        //  异步函数存储
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        let resolve = (value) => {
            if (this.state === PENDING) {
                this.state = FULFILLED;
                this.value = value;
                this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
                    resolve(value)
                })
            }
        }

        let reject = (reason) => {
            if (this.state === PENDING) {
                this.state = REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
                    reject(reason)
                })
            }

        }

        try {
            excutor(resolve, reject)
        } catch (error) {
            throw error;
        }
    }

    then(onFulfilled, onRejected) {
        const promise2 = new basicPromise((resolve, reject) => {
            if (this.state === FULFILLED) {
                if (typeof onFulfilled === 'function') {
                    try {
                        setTimeout(() => {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x)
                        }, 0)
                    } catch (error) {
                        reject(error)
                    }

                } else {
                    resolve(this.value);
                }
            } else if (this.state === REJECTED) {
                if (typeof onRejected === 'function') {
                    try {
                        setTimeout(() => {
                            const x = onRejected(this.reason);
                            resolvePromise(promise2, x)
                        }, 0)
                    } catch (error) {
                        reject(error)
                    }
                } else {
                    reject(this.reason)
                }
            } else {
                // 执行函数为异步函数

                this.onFulfilledCallbacks.push((value) => setTimeout(() => {
                    if (typeof onFulfilled === 'function') {
                        try {
                            const x = onFulfilled(value)
                            resolvePromise(promise2, x)
                        } catch (error) {
                            reject(error)
                        }
                    } else {
                        resolve(value)
                    }
                }, 0))

                this.onRejectedCallbacks.push((reason) => setTimeout(() => {
                    if (typeof onRejected === 'function') {
                        try {
                            const x = onRejected(reason)
                            resolvePromise(promise2, x)
                        } catch (error) {
                            reject(error)
                        }
                    } else {
                        reject(reason)
                    }
                }, 0))
            }
        });
        return promise2
    }
}

let p1 = new basicPromise((resolve, reject) => {
    setTimeout(() => {
        console.log('立即执行');
        //  resolve('成功');
        reject('失败');
    }, 1000)

})

then方法执行的过程

执行 [[Resolve]](promise2, x) 需遵循以下步骤:

  1. x 与 promise2 相等

    如果 promise2 和 x 指向同一对象,以 TypeError 为拒因拒绝 promise2

  2. 如果 x 为 Promise,依据状态不同:

    如果 x 处于待定状态, promise2 需保持为待定状态直至 x 被解决或拒绝

    如果 x 处于兑现状态,用与 x 相同的终值解决 promise2

    如果 x 处于拒绝状态,用与 x 相同的拒因拒绝 promise2

  3. 如果 x 是一个对象或者函数

    把 x.then 赋值给 then

    如果取 x.then 的值时抛出错误 e ,则以 e 为拒因拒绝 promise2

    如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise:

     如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise2, y)
    
     如果 rejectPromise 以拒因 r 为参数被调用,则以拒因 r 拒绝 promise2
    
     如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
    
  4. 如果调用 then 方法抛出了异常 e:

    如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之

    否则以 e 为拒因拒绝 promise2

  5. 如果 then 不是函数,以 x 为参数解决 promise2

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) { //  promise2 和 x 指向同一对象,以 TypeError 为拒因拒绝 promise2
        reject(new TypeError('Chaining cycle detected for promise'));
    } else if (typeof x === 'function' || (typeof x === 'object' && x !== null)) { // 如果 x 是一个对象或者函数,上面第 2 点,如果 x 为 Promise,由于 Promise 也是一个对象,所以不用单独处理了
        let called = false; // 是否被调用,用于处理当 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,仅首次调用并忽略剩下的调用
        try {
            const then = x.then;
            if (typeof then === 'function') { // then 为函数
                then.call(x, y => { // then 函数执行并接收两个回调函数
                    if (called) return;
                    called = true;
                    resolvePromise(promise, y, resolve, reject);
                }, r => {
                    if (called) return;
                    called = true;
                    reject(r);
                });
            } else {
                resolve(x); // 处理上述第 3 点中的第 4 点,  then 不是函数,以 x 为参数解决 promise2
            };
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }
    } else {
        resolve(x); // 如果 x 不为对象或者函数,以 x 为参数解决 promise2
    }
};


class basicPromise {
    constructor(excutor) {
        this.state = PENDING; // 状态
        this.value = undefined; // 成功返回
        this.reason = undefined; // 失败返回

        //  异步函数存储
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        let resolve = (value) => {
            if (this.state === PENDING) {
                this.state = FULFILLED;
                this.value = value;
                this.onFulfilledCallbacks && this.onFulfilledCallbacks.forEach(resolve => {
                    resolve(value)
                })
            }
        }

        let reject = (reason) => {
            if (this.state === PENDING) {
                this.state = REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks && this.onRejectedCallbacks.forEach(reject => {
                    reject(reason)
                })
            }

        }

        try {
            excutor(resolve, reject)
        } catch (error) {
            throw error;
        }
    }

    then(onFulfilled, onRejected) {
        const promise2 = new basicPromise((resolve, reject) => {
            if (this.state === FULFILLED) {
                if (typeof onFulfilled === 'function') {
                    try {
                        setTimeout(() => {
                            const x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject)
                        }, 0)
                    } catch (error) {
                        reject(error)
                    }

                } else {
                    resolve(this.value);
                }
            } else if (this.state === REJECTED) {
                if (typeof onRejected === 'function') {
                    try {
                        setTimeout(() => {
                            const x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject)
                        }, 0)
                    } catch (error) {
                        reject(error)
                    }
                } else {
                    reject(this.reason)
                }
            } else {
                // 执行函数为异步函数

                this.onFulfilledCallbacks.push((value) => setTimeout(() => {
                    if (typeof onFulfilled === 'function') {
                        try {
                            const x = onFulfilled(value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    } else {
                        resolve(value)
                    }
                }, 0))

                this.onRejectedCallbacks.push((reason) => setTimeout(() => {
                    if (typeof onRejected === 'function') {
                        try {
                            const x = onRejected(reason)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    } else {
                        reject(reason)
                    }
                }, 0))
            }
        });
        return promise2
    }
}

let p1 = new basicPromise((resolve, reject) => {
    setTimeout(() => {
        console.log('立即执行');
        //  resolve('成功');
        reject('失败');
    }, 1000)

})

原文链接:blog.csdn.net/qq_41800366…