Promise原理及源码解释

有不对的,可以指出来,我这里只是想记一下笔记,方便我以后看。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
   <script>
    let st = setTimeout;
    const FULL_FILLED = 'fullFilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    const PENDING = 'pending';//这里用的setTimeout做异步操作,所以在执行异步之前的时间里,状态都是pending
    let count = 0;
    let Promise = function (fn) {//fn就是promise中的函数参数,这个参数有两个内部定义好的resolve和reject函数参数
        this.id = count++;
        this.status = PENDING;
        this.successCallbacks = [];//用来保存then里边的成功回调函数
        this.failedCallbacks = [];//用来保存then里边失败的回调函数
        let resolve = (v)=> {//promise的resolve执行,后会执行then中的成功回调函数,这个v参数,会传过去
            setTimeout(()=>{
                // resolve(value);
                this.value = v;
                this.status = FULL_FILLED;//如果成功会从pending状态变成fullFilled
                this.successCallbacks.forEach( fn => fn(this.value) )
            })
        }
        let reject = (v) => {
            setTimeout(()=>{
                // reject(value);
                this.value = v;
                this.status = REJECTED;//失败的话从pending状态变成rejected状态
                this.failedCallbacks.forEach( fn => fn(this.value) )
            })
        }
        try {
            fn(resolve,reject)
        } catch (e) {
            reject(e); // new Promise().then 执行失败
        }
    }
    function excutePromise (promiseOrVal,resolve,reject) {//这是第一个参数,是判断then中的返回是一个【promise】还是【普通的基本类型值】
        if (promiseOrVal instanceof Promise) {
            // 还没有写 (then  从promise中取值)
            promiseOrVal.then((v)=>{
                excutePromise(v,resolve,reject);//这个就是一直递归判断then中返回的是不是promise还是基本值的函数
            });
        } else {
            // value 基本数据类型
            resolve(promiseOrVal);  // then中如果返回的是【基本类型的值】执行resolve函数,就直接进行到下一个的.then的回调函数里面,否则的话就是promise,继续进行循环递归去判断返回的是promise还是基本类型值
        }
    }

    // then 一定是要返回Promise供外部.then
    Promise.prototype.then = function (onFullFilledFn,onRejectedFn) {
        let chainPromise;//这个结果就是then的返回值,一定要是promise,供外部的.then
        // 如果当前,3秒以内,状态是【Pending】
        if (this.status === PENDING) {//如果是pending状态,就说明,也不知道要走成功还是失败,所以有两种可能
          chainPromise = new Promise((resolve,reject)=>{
                  // 是pending状态,先把成功或者是失败的回调函数保存起来,等待状态改变后,直接调用,这个目的就是保存函数
            this.successCallbacks.push(()=>{
               try {
                  setTimeout(()=>{
                        // resovle后才会被发布,所执行
                    let value = onFullFilledFn(this.value);
                    // value有可能是Promise, 也有可能是一般的值
                    excutePromise(value,resolve,reject);//这个函数就是去判断返回的值是否是promise还是基本值,基本值的话,就会执行resolve,想定与放行开关,进入到下一个then中
                  })
               }catch(e) {
                   reject(e);
               }
            });
            this.failedCallbacks.push(()=>{
                try {
                   setTimeout(()=>{
                        // reject后才会被发布,所执行
                        let value = onRejectedFn(this.value);
                        // value有可能是Promise, 也有可能是一般的值
                        excutePromise(value,resolve,reject);
                   })
               }catch(e) {
                   reject(e);
               }
            })
          });
        } 

        if (this.status === FULL_FILLED) {//如果状态是成功,直接走成功回调
            chainPromise = new Promise((resolve,reject) => {
                try {
                   setTimeout(()=>{
                    let value = onFullFilledFn(this.value);
                    excutePromise(value,resolve,reject);
                   })
                } catch (e) {
                    reject(e);
                }
            });
        }

        if (this.status === REJECTED) {//如果状态是失败
            chainPromise = new Promise((resolve,reject) => {
                try {
                    let value = onRejectedFn(this.value);
                    excutePromise(value,resolve,reject);
                } catch (e) {
                    reject(e);
                }
            });
        }
        return chainPromise;
    }
    





    // 模拟3组异步
    // 返回的是Promise实例
    new Promise(function (resolve,reject) {
        console.log('promise执行了');//1
        st(()=>{
            console.log('第1件事。。。');//2
            resolve('abcd');
        },3000);
    })
    .then( (data)=> {
        return new Promise((resovle,reject)=>{
            st(()=>{
                console.log('第2件事');//3
                resovle('xxx');//这个执行了,才会执行下一个then,它就是一个开关作用,这个参数会作为下一个then的实参,
            },3000);
        });
    })
    .then((d)=>{
        console.log('结束了',d);//4,d的值:【d:'xxx'】
    })


   </script>


</body>
</html>

.then一定是一个promise,供外部(后续)的.then才能执行,
.then 是立刻执行的,没办法控制它停止,每个then里的回调函数,有可能是一个promise
或者一个普通的基本类型的值,如果是promise,只有resolve,才会执行下一个then里的
回调函数,否则直接往下执行;(有一个递归就是判断then里的回调函数是不是一个promise,如果是
就继续递归)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2中的nextTick方法是用来在下一次DOM更新循环结束之后执行延迟回调的方法。它的核心原理是利用了浏览器的异步任务队列机制,将回调函数加入到任务队列中,在下一次DOM更新循环结束之后执行。 具体实现原理如下: 1. nextTick方法会先判断是否已经有一个回调队列,如果没有就创建一个空数组作为队列。 2. 将回调函数加入到队列中。 3. 判断是否已经有一个异步任务,如果没有就创建一个异步任务,并将其加入到任务队列中。 4. 当异步任务执行时,会依次执行回调函数队列中的所有函数。 下面是nextTick的源码: ```javascript export function nextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true if (useMacroTask) { macroTimerFunc() } else { microTimerFunc() } } // $flow-disable-line if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve }) } } ``` 其中callbacks是一个数组,用来保存回调函数队列。pending表示是否已经有一个异步任务在执行,useMacroTask表示是否使用宏任务,用来区分不同的环境(浏览器、node等)。 在上面的代码中,先把回调函数加入到队列中,然后判断是否已经有一个异步任务在执行。如果没有,就创建一个异步任务并加入到任务队列中。如果使用宏任务,就使用setTimerout来创建异步任务,如果不使用宏任务,就使用微任务(Promise)。 最后,如果没有传入回调函数,但是环境支持Promise,则返回一个Promise对象,以便在异步任务执行完毕后可以进行链式调用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值