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

  • 相关阅读:
    微服务架构技术栈选型手册(万字长文)
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    Visual Studio 2013 always switches source control plugin to Git and disconnect TFS
    MFC对话框中使用CHtmlEditCtrl
    ATL开发 ActiveX控件的 inf文件模板
    ActiveX: 如何用.inf和.ocx文件生成cab文件
    Xslt 1.0中使用Array
    如何分隔两个base64字符串?
    An attempt was made to load a program with an incorrect format
    JQuery 公网 CDN
  • 原文地址:https://www.cnblogs.com/sowhite/p/8946561.html
Copyright © 2011-2022 走看看