搞懂promise【2】

promise的串联

当后续的Promise需要用到之前的Promise的处理结果时,需要Promise的串联

Promise对象中,无论是then方法还是catch方法,它们都具有返回值,返回的是一个全新的Promise对象,它的状态满足下面的规则:

  1. 如果当前的Promise是未决的,得到的新的Promise是挂起状态
  2. 如果当前的Promise是已决的,会运行响应的后续处理函数,并将后续处理函数的结果(返回值)作为resolved状态数据,应用到新的Promise中;如果后续处理函数发生错误,则把返回值作为rejected状态数据,应用到新的Promise中。

后续的Promise一定会等到前面的Promise有了后续处理结果后,才会变成已决状态

const pro1 = new Promise((resolve, reject) => {
            resolve(1)
        })
        const pro2 = pro1.then(result => {
            return result * 2
        });
      
        pro2.then(result => console.log(result * 2), err => console.log(err * 3))
  • 输出 4
const pro1 = new Promise((resolve, reject) => {
            throw 1;
        })
        const pro2 = pro1.then(result => {
            return result * 2
        }, err => {
            return err * 3; // 3
        });
       
        //pro2类型:Promise对象
        //pro2的状态:
        pro2.then(result => console.log(result * 2), err => console.log(err * 3))

        //输出:6

pro2.then的时候运行第一个函数,因为pro1的后续处理没有错误。

const pro1 = new Promise((resolve, reject) => {
            throw 1;
        })
        const pro2 = pro1.then(result => {
            return result * 2
        }, err => {
            throw err; // 1
        });
        pro2.then(result => console.log(result * 2), err => console.log(err * 3))
// 输出3
  • pro抛出了一个错误,pro1的后续处理也抛出了一个错误,那么pro2的后续处理就是rejected,运行第二函数。
const pro1 = new Promise((resolve, reject) => {
            throw 1;
        })
        const pro2 = pro1.then(result => {
            return result * 2
        }, err => {
            return err * 3; // 3
        });
        //返回的又是一个新的promise 没有pro2什么事
        pro1.catch(err => {
            return err * 2;
        })
       
       //pro1后续处理正常进行,没有抛出错误。所以这里运行第一个函数。
        pro2.then(result => console.log(result * 2), err => console.log(err * 3))

        //输出:6

如果前面的Promise的后续处理,返回的是一个Promise,则返回的新的Promise状态和后续处理返回的Promise状态保持一致。

const pro1 = new Promise((resolve,reject)=>{
	resolve(1);
})
const pro2 = new Promise((resolve,reject)=>{
	resolve(2);
})

const pro3 = pro1.then(data=>{
	return pro2;
});
pro3.then(data=>{
	console.log(data); // 2
})
const pro1 = new Promise((resolve,reject)=>{
	resolve(1);
})
const pro2 = new Promise((resolve,reject)=>{
	setTimeout(()=>{
		resolve(2);
	},3000)
	
})

const pro3 = pro1.then(data=>{
	console.log('xxxx')
	return pro2;
});
pro3.then(data=>{
	console.log(data); // 等3s输出2
})
  • 先输出 ‘xxxx’ 等3s输出2
const pro1 = new Promise((resolve, reject) => {
            resolve(1);
        })

        const pro2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(2);
            }, 3000);
        })

        pro1.then(result => {
            console.log("结果出来了,得到的是一个Promise")
            return pro2;
        }).then(result => {
            console.log(result)
        }).then(result => {
            console.log(result)
        })
  • 先输出:结果出来了,得到的是一个Promise
  • 等3s输出2
  • 由于第二个then返回的undefined,所以等3s输出2后马上输出undefined。
//获取李华所在班级的老师的信息
        //1. 获取李华的班级id   Promise
        //2. 根据班级id获取李华所在班级的老师id   Promise
        //3. 根据老师的id查询老师信息   Promise
        const pro = ajax({
            url: "./data/students.json"
        })
        pro.then(resp => {
            for (let i = 0; i < resp.length; i++) {
                if (resp[i].name === "李华") {
                    return resp[i].classId; //班级id
                }
            }
        }).then(cid => {
            return ajax({
                url: "./data/classes.json?cid=" + cid
            }).then(cls => {
                for (let i = 0; i < cls.length; i++) {
                    if (cls[i].id === cid) {
                        return cls[i].teacherId;
                    }
                }
            })
        }).then(tid => {
            return ajax({
                url: "./data/teachers.json"
            }).then(ts => {
                for (let i = 0; i < ts.length; i++) {
                    if (ts[i].id === tid) {
                        return ts[i];
                    }
                }
            })
        }).then(teacher => {
            console.log(teacher);
        })

promise 的串联

const MyPromise = (() => {

    const PENDING = 'pending', //状态变量
        RESOLVED = 'resolved',
        REJECTED = 'rejected',
        // 符号变量外面的访问不到
        promiseStatus = Symbol('PromisrStatus'), //promise的状态
        promiseValue = Symbol('promiseValue'), // promise的状态数据
        changeStatus = Symbol('changeStatus'), //该变promise的状态
        thenables = Symbol('thenables'), //thenables作业队列
        catchables = Symbol('catchables'), //catchables作业队列
        settleHandle = Symbol('settleHandle'), //后续处理函数
        linkPromise = Symbol('linkPromise'); //返回的promise

    return class MyPromise {
        /**
         * 
         * @param {*} executor 未决阶段(pending状态)下的处理函数
         */
        constructor(executor) {
            //刚开始为pending
            this[promiseStatus] = PENDING;
            //刚开始状态数据为undefined
            this[promiseValue] = undefined;
            //初始化作业队列
            this[thenables] = [];
            this[catchables] = [];
            /**
             * executor 为new Promise(executor)传递进来的函数
             *  1.要同步执行,所在构造器函数里面要调用一次。
             *  2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
             */
            /**
             * resolve有改变状态的能力
             * 由于要改变状态和状态数据,所以要用this,
             * 但是外面是直接调用resolve,this指向全局
             * 所以这里用箭头函数方便点
             * 然后分析reject函数也是如此,所以写个函数
             * @param {*} data 状态数据
             */
            const resolve = (data) => {
                this[changeStatus](data, RESOLVED, this[thenables]);
            };

            /**
             * reject也有改变状态的能力
             * @param {*} error 状态数据
             */
            const reject = (error) => {
                this[changeStatus](error, REJECTED, this[catchables]);
            }
            /**
             * 调用executor函数,执行同步代码
             * 如果这里抛出错误就要推向rejected状态
             * 所以要捕获错误,然后推向rejected
             * */
            try {
                executor(resolve, reject);
            } catch (err) {
                reject(err);
            }
        }
        /**
         * 改变状态的函数
         * @param {*} data 状态数据
         * @param {*} status 状态
         * @param {*} queue 执行的作业队列
         */
        [changeStatus](data, status, queue) {
            //状态不可逆或者说只有在pending状态下才能推向resolved或rejected
            if (this[promiseStatus] !== PENDING) {
                // 如果不是pending直接结束
                return;
            }
            // 是pending才推向后续状态
            this[promiseStatus] = status;
            this[promiseValue] = data;
            //状态改变了 要运行作业队列
            queue.forEach((handle) => handle(data));
        }

        /**
         * 后续处理函数
         * @param {*} handle 后续处理函数
         * @param {*} immediatelyStatus 状态
         * @param {*} queue 作业队列
         */
        [settleHandle](handle, immediatelyStatus, queue) {
            //handle 不是一个函数直接返回
            if (typeof handle !== 'function') {
                return;
            }
            if (this[promiseStatus] === immediatelyStatus) {
                setTimeout(() => {
                    handle(this[promiseValue]);
                })
            } else {
                queue.push(handle);
            }
        }
        [linkPromise](thenable, catchable) {
            return new MyPromise((resolve, reject) => {
                this[settleHandle](data => {
                    try {
                        const result = thenable(data); // 返回的结果 当前promise的处理结果
                        resolve(result); //然后返回的promise推向resolved状态
                    } catch (err) {
                        //出了问题才推向rejected
                        reject(err);
                    }

                }, RESOLVED, this[thenables]);
                this[settleHandle](err => {
                    try {
                        const result = catchable(err); // 返回的结果 当前promise的处理结果
                        resolve(result); //然后返回的promise推向resolved状态
                    } catch (err) {
                        reject(err);
                    }
                }, REJECTED, this[catchables]);
            })
        }

        then(thenable, catchable) {
            //调用then方法传递一个函数,或者两个函数
            //如果状态是resolved那么立即执行
            //如果不是resolved那么就加入到作业队列里面,等到是resolved才执行
            //reject也是同样的处理

            //状态是resolved那么立即执行
            // if (this[promiseStatus] === RESOLVED) {
            //     //由于是异步执行,并且真实的效果是放在微队列里面的,而在浏览器环境中没有办法放入微队列里面,
            //     //所以这里采用setTimeout来模拟,放入到宏任务里面
            //     setTimeout(() => {
            //         //将数据传给他,然后外面调用的函数中的data才有值
            //         thenable(this[promiseValue]);
            //     })
            // } else {
            //     // 不是resolved那么就加入到作业队列里面
            //     this[thenables].push(thenable);
            // }

            // this.catch(catchable);
            // this[settleHandle](thenable, RESOLVED, this[thenables]);
            // this.catch(catchable);

            // 调用then要返回一个promise
            return this[linkPromise](thenable, catchable);
        }
        catch (catchable) {
            // this[settleHandle](catchable, REJECTED, this[catchables]);
            return this[linkPromise](thenable, catchable);
        }
    }
})();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值