开头说明

文档最后有完整的依照Promise/A+规范手写的Promise代码

promise实例化对象的属性值 [promiseState]

  • pending 等待
  • resolve / fullfilled 成功
  • reject 失败

promise实例化对象的属性值 [promiseResult]

  • 保存着异步操作 [成功/失败] 返回的值
  • 只有resolvereject这两个函数可以修改这个值

promise的API

Promise的构造函数 [Promise(executor){}]

  • executor函数:执行器函数 形如 (resolve, reject) => {}
  • resolve 函数:执行器函数内部成功以后执行的函数
  • reject 函数:执行器函数内部失败以后执行的函数

执行器函数executor的内容会在Promise的内部同步调用

Promise.prototype.then方法 [(onResolved, onRejected){}]

  • onResolved函数:Promise对象的状态变成resolve的时候,执行的回调函数 (value) => {...}
  • onRejected函数:Promise对象的状态变成reject的时候,执行的回调函数 (reason) => {...}

valuereason是执行resolvereject函数返回的值
then方法会重新返回一个新的Promise对象

Promise.prototype.catch方法 [(onRejected){}]

  • onRejected函数:Promise对象的状态变成reject的时候,执行的回调函数 (reason) => {...}

Promise.resolve方法 属于Promise函数对象 [(value) => {}]

  • value是传入的值 不同的value会导致返回的Promise对象的状态不一致

如果value是非Promise的实例化对象 那么返回resolve状态的Promise对象 返回值是value
如果value是Promise的实例化对象 返回状态和返回值由传入的Promise的实例化对象决定

    Promise.resolve(111) 
    /* promiseState='resolve' promiseResult=111 */

    Promise.resolve(true) 
    /* promiseState='resolve' promiseResult=true */

    Promise.resolve(new Promise(resolve,reject) => {
        resolve('OK')
        /* promiseState='resolve' promiseResult='OK' */

        reject('Error') 
        /* promiseState='reject' promiseResult='Error' */
    })

Promise.reject方法 属于Promise函数对象 [(reason) => {}]

  • reason是传入的值 无论传入什么值 最后都会返回一个状态为reject的Promise对象

执行该函数得到的Promise对象需要调用catch函数 否则浏览器会报错

    Promise.resolve(111) 
    /* promiseState='reject' promiseResult=111 */
    
    Promise.resolve(true) 
    /* promiseState='reject' promiseResult=true */

    const myPromise =  Promise.resolve(new Promise(resolve,reject) => {
        resolve('OK') 
        /* promiseState = 'reject' promiseResult = new Promise(...)
           返回的Promise对象的状态为resolve */

        reject('Error') 
        /* promiseState = 'reject' promiseResult = new Promise(...)
           返回的Promise对象的状态为reject */
    })
    myPromise.catch((reason) => {
        console.log(reason)
    })

Promise.all方法 属于Promise函数对象 [(promises) => {}]

  • promises是promise对象构成的数组 返回一个新的Promise对象

如果promises中所有的Promise对象的状态都为resolve 那么返回的Promise的状态为resolve 值为promises中所有成功对象的返回值
如果promises中有一个对象的状态为reject 那么返回的Promise的状态为reject 值为promises中第一个失败对象的返回值

Promise.race方法 属于Promise函数对象 [(promises) => {}]

  • promises是Promise对象构成的数组 返回一个新的Promise对象

返回的Promise对象的状态由promises数组中第一个完成状态修改的对象决定(setTimeout会影响最后的结果)

Promise的关键问题

Promise对象状态的修改

  • resolve函数可以使promiseStatus的状态变成resolve
  • reject函数和throw操作可以使promiseStatus的状态变成rejected

Promise对象执行多个回调函数

    let p = new Promise((resolve,reject) => {
        resolve('OK');
    })

    p.then(value => {
        console.log(value)
    })
    p.then(value => {
        alert(value)
    })

可以为Promise对象指定多个回调函数(then)会按定义的先后去执行

Promise状态改变和回调函数执行的先后顺序

  • 情况1 同步操作
    let p = new Promise((resolve,reject) => {
        resolve('OK');
    })
    p.then(value => {
        console.log(value)
    })

这种情况下 因为exector执行函数是同步调用的 resolve函数也是 所以先执行状态改变的函数 再去执行then回调函数

  • 情况2 异步操作 实际开发中占绝大部分
    let p = new Promise((resolve,reject) => {
        // 使用延时函数模拟接口调用的过程
        setTimeout(() => {
            resolve('OK');
        },1000)
    })
    p.then(value => {
        console.log(value)
    })

这种情况下 resolve函数延迟了一秒钟才执行 所以回调函数then会先执行 等promiseStatus的值改变后 再去调用成功的回调函数

Promise的回调函数then的返回结果

  • promise对象的回调函数then返回的也是一个promise对象 promiseStatuspromiseResult的返回值规则和Promise.resolve()一致

Promise对象的链式调用

  • 因为promise对象的回调函数then返回的也是一个promise对象 所以支持链式调用

Promise的异常穿透

    let p = new Promise((resolve,reject) => {
        // resolve('OK)
        // throw 'ERR'
    }).then(value => {
        console.log(111)
    }).then(value => {
        console.log(2222)
    }).then(value =>{
        console.log(33333)
    }).catch(reason => {
        console.log(reason)
    })

在使用Promise进行链式调用的时候,不需要为每一个then回调函数指定错误的回调函数
只需要在最后加上catch回调 只要链式调用过程中 promiseResult的状态变成了rejected 就会执行catch操作

Promise的终止操作

  • 因为then函数的特性 返回的promise对象的promiseStatus的值决定着后续的操作
  • 所以 有且只有一种方式终止操作 返回一个pending状态的promise对象
  • 返回ture null之类的都是resolve状态 throw操作会被catch捕获
    let p = new Promise((resolve,reject) => {
        resolve('Ok')
    }).then(value => {
        console.log(111);
        return new Promise(() => {});//pending状态的promise对象
    }).then(value => {
        console.log(2222)
    }).then(value =>{
        console.log(33333)
    }).catch(reason => {
        console.log(reason)
    })
    // 上述代码只会打印出111

根据Promise/A+规范实现Promise

function Promise(executor) {
    this.PromiseStatus = 'pending';
    this.PromiseResult = 'null';
    this.resolveCallbacks = [];
    this.rejectCallbacks = [];

    /**如果不定义的话 resolve和reject函数的this指向window 无法修改状态和返回值 */
    const self = this 

    function resolve(data) {
        if(self.PromiseStatus !== 'pending') return ;
        self.PromiseStatus = 'resolved';
        self.PromiseResult = data;
        /**处理异步操作 可以有多个回调函数 */
        self.resolveCallbacks.forEach(onResolved => {
            onResolved(self.PromiseResult)
        })
    }

    function reject(data) {
        if(self.PromiseStatus !== 'pending') return ;
        self.PromiseStatus = 'rejected';
        self.PromiseResult = data;
        /**处理异步操作 可以有多个回调函数 */
        self.rejectCallbacks.forEach(onRejected => {
            onRejected(self.PromiseResult)
        })
    }

    try{
        /**resolve 和 reject是实参 */
        executor(resolve, reject);
    }catch(e){
        /**处理throw 抛出异常的情况 */
        reject(e);
    }
}

Promise.prototype.then = function(onResolved, onRejected){
    const self = this;

    /**返回值必须是promise对象 */
    return new Promise((resolve,reject) => {
        /**判断用户是否传参 如果不传回调函数的话 默认补上 */
        if(typeof onRejected !== 'function'){
            onRejected = (reason) => {
                throw reason
            }
        }
        if(typeof onResolved !== 'function'){
            onResolved = value => value
        }
        /**封装处理函数 */
        function callback(type){
            try{
                let result = type(self.PromiseResult);
                if(result instanceof Promise){
                    /*
                    **  调用then方法 来判断返回的promise的状态是成功还是失败
                    **  如果result没有改变自己的状态 那么就返回pending状态 改变了就会走then方法
                    */
                    result.then(value => {
                        resolve(value);
                    }, reason => {
                        reject(reason);
                    })
                }else{
                    resolve(result);
                }
            }catch(e){
                /**处理throw操作 */
                reject(e)
            }
        }
        /**根据PromiseStatus的值调用对应的回调函数 */

        /**处理同步的情况 */
        if(this.PromiseStatus === 'resolved'){
            callback(onResolved);
        }
        if(this.PromiseStatus === 'rejected'){
            callback(onRejected);
        }

        /**处理异步的情况 then方法执行的时候 promise对象的状态还未改变 */
        if(this.PromiseStatus === 'pending'){
            /*  
            **  保存成功和失败的回调函数供Promise构造函数中的resolve和reject调用
            **  需要考虑到多个then回调函数的情况
            */
            this.resolveCallbacks.push(function(){
                callback(onResolved);
            });
            this.rejectCallbacks.push(function(){
                callback(onRejected);
            });
        }
    })
}

Promise.prototype.catch = function(onRejected) {
    return this.then(undefined,onRejected);
}
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐