zoukankan      html  css  js  c++  java
  • promise的实现方式和运行机制

    promise的规范其实种类很多,我们最常用的是promise/A+

    这篇文章会先将一个类似于promise的构造函数怎么写,网上很多教程并没有实现A+规范,只是看起来像而已

    然后我们深入探究如何一步一步实现真正的promise/A+规范的要求。

    首先我们实现一个简单的promise,这个promise类似于express的路由处理

    express的路由处理以next的方式一层一层的进入, 直到不再next。这个很像promise呐,也是比较懒,没有去看源码,但试着实现一个那种异步,会发现其实蛮简单的。

    ok,废话少说,先搞一个

    需求

    1. promise拥有then和catch方法

    2. promise出错时调用catch,有两种错误,主动跑错可以用next(err)

    3. promise的第一个参数为function, 第一个参数为next,其他参数可以传递到下一步。

    然后我们要实现的功能如下

    new Promise(next => {
      setTimeout(() => {
        console.log(1);
        next(null, 2);
      }, 1000);
    })
      .then((next, arg) => {
        setTimeout(() => {
          console.log(arg);
          next();
        }, 1000);
      })
      .then((next, arg) => {
        setTimeout(() => {
          console.log(arg);
          next();
        }, 1000);
      })
      .catch(err => console.error(err));

    实现

    首先我们实现then和catch方法

      我们建立一个回调队列和一个出错回调1

      1)then里的东西都会被推进去

      2)catch会去替换默认的回调方法

      3)next函数会执行resovleCallbacks里的下一个方法 

    function Promise(execute) {
      let resolveCallbacks = [];
      let rejectCallbacks = err => console.error(err);
      this.then = fn => {
        resolveCallbacks.push(fn);
        return this;
      };
      this.catch = fn => {
        rejectCallback = fn;
        return this;
      };
    
      execute(next);
    
      function next() {
        const nextCallback = resolveCallbacks.shift();
        nextCallback && nextCallback(next);
      }
    }

    为了捕捉错误 

      try {
        execute(next);
      } catch (err) {
        rejectCallback(err);
      }

    我们添加如上的错误捕捉机制

    假如果主动跑错就用next(err)

    没有出错的话就next(null, arg1, arg2)这样传参

    所以我们修改next方法

      function next(...args) {
        if(args[0]){
            return rejectCallback(args[0]);
        }else{
            const nextCallback = resolveCallbacks.shift();
            try {
              nextCallback && nextCallback(next, ...args.slice(1));
            } catch (err) {
              rejectCallback(err);
            }
        }
      }

    至此就实现完成了,很简单吧

     game over

    Promise/A+

    但事实上一个伟大的promise/A+规范的实现可不止这么简单。

    然后我们来看看一个promise/A+规范是什么样子的

    1. 状态管理pendding fullfilled(resolved) rejected 三种

    2. then返回一个新的promise, then的两个参数是function,是上一步的成功和失败的回调

    3. 不同的promise可以接起来使用

    以上是主要的规范 更加具体的看这里

    要想实现promise/A+,首先要搞清楚它的工作原理

    按照规范 最麻烦的是then方法的处理,

    但是记住两点就Ok

    1. 不同的promise的状态不同,所以then方法不可以返回this,而是应该返回一个新的promise

    2. then的执行实在resolve完成后,所以在then方法里把onResolved方法修改为then的第一个参数

    3. 在promise中then里的函数如果返回值是promise就必须等到promise执行完成才可以到下一步, 对此我们巧妙的运用promise的then,只要把resolve放到then里边就会延迟resolve的发生

    return x.then(resolve);

    4. 在promise中then里的函数如果返回值不是promise那就直接执行 然后resolve

    5. executor应该是慢一点开始,所以用了setTimeout,因为首先需要执行的是then方法,待一切promise队列就绪后才可以开始。

    6. 执行then的时候可能已经resolved了,那么这个时候就立即执行,如果还是pending状态的话那么就放到执行完成的回调函数里。

    知道以上几点之后 就可以很轻松的看懂代码了

    首先是构造函数

    function Promise(executor) {
        let onResolved = null;
        let onRejected = null;
        this.status = 'pending';
        let self = this;
    
        let resolve = data => {
            self.data = data || null;
            self.status = 'resolved';
            typeof onResolved === 'function' && onResolved(data);
        }
    
        let reject = (err) => {
            self.status = 'rejected';
            typeof onRejected === 'function' && onRejected(data);
        }
    
        this.then = onResolvedFn => {
            
        }
    
        executor(resolve, reject);
    }

    然后是then方法

        if (self.status === 'pending') {
                console.log('promise is pending, add callback')
                return new Promise(resolve => {
                    onResolved = data => {
                        let x = onResolvedFn(self.data)
                        if (x instanceof Promise) {
                            return x.then(resolve);
                        } else {
                            resolve();
                        }
                    }
                })
            }
            
            if (self.status === 'resolved') {
                console.log('promise is resolved, execuate')
                return new Promise(resolve => {
                    let x = onResolvedFn(self.data)
                    if (x instanceof Promise) {
                        return x.then(resolve);
                    } else {
                        resolve();
                    }
                })
            }

    then方法实现后,然后我们实现一个Promise.resolve方法

    Promise.resolve = data => new Promise(resolve => setTimeout(() => resolve(data)));

    关于catch和promise的错误处理机制这里就不详细的写了,反正一切都为了简单看懂。

    参考文章: https://zhuanlan.zhihu.com/p/21834559

  • 相关阅读:
    flask之视图
    android studio 配置阿里云镜像 加速
    mac idea phpstorm 提示 clear read-only status 解决办法
    如何给网站一键变黑?如哀悼日,一行css代码解决
    Android base64加密中文乱码问题解决记录
    微信Android app支付 重要记录,重要!!
    mysql 数据库拷贝innodb 操作注意事项,宝塔面板
    Linux 服务器使用shell脚本 实现 间隔N秒访问url
    echarts pie饼图块颜色设置
    Linux 服务器 node 节点满了引发的灾难,请定期清理node节点
  • 原文地址:https://www.cnblogs.com/sowhite/p/8946561.html
Copyright © 2011-2022 走看看