zoukankan      html  css  js  c++  java
  • Promise原理 && 简单实现

    Promise原理

    参考https://github.com/chunpu/promise/blob/master/promise.js

    个人认为原博的实现有点问题 在next函数的实现上, 会导致无限的调用

    看看一般Promise的用法

    promise = new Promise(function(resolve, reject) {
      //...
        resolve(1);
      //...
    })
    .then(function(val){}, functioin(err){})
    .then(function(val){}, functioin(err){})
    

    显然要实现的功能是这样的
    Promise对象有then方法
    Promise对象接受一个参数fn(resolve, reject)
    Promise可以连续的then调用

    function Promise(resolver) {
      var queue = [];//链式调用数组
      resolver(resolve, reject);
    
      //state 0 是resolve
      function next(state, val){
        var arr;
        if(arr = queue.shift()){
          arr[state](val);
        }
      }
    
      function resolve(x){
        next(0, x)
      }
      function reject(reason){
        next(1, reason);
      }
    
      //Promise最明显的特征 是可以then  then接收两个参数
      //then就是将传入的函数放入队列中
      this.then = function(resolve, reject){
        queue.push([resolve, reject]); //resovle  reject  这两个参数也都是函数
      }
    }
    
    
    var p = new Promise(function(resolve){
      resolve('ok')
    })
    
    p.then(function(x){
      console.log(x);
    })
    

    有个问题 那就是创建一个Promise对象的时候就调用了 resolver(resolve, reject); 也就是调用了resolve('ok') 也就是调用了next 也就是使queue函数出队列并执行

    但是这个时候 queue 还没有push任何值 执行不能继续 毕竟这个是在Promise对象完成创建之后才调用then

    为了使next在then中的函数全部进到队列之后再执行 用一个setTimeout把 next中的逻辑包裹

    function Promise(resolver) {
      var queue = [];
      resolver(resolve, reject);
    
      function next(state, val){
        var arr;
        //为了使resolve晚于 then 执行  暂时用一个setTimeout
        setTimeout(function(){
          if(arr = queue.shift()){
            arr[state](val);
          }
        }, 0);
      }
    
      function resolve(x){
          next(0, x);
      }
      function reject(reason){
          next(1, reason);
      }
    
      this.then = function(resolve, reject){
        queue.push([resolve, reject]);
      }
    }
    
    var p = new Promise(function(resolve){
      setTimeout(function(){
        resolve('ok')
      },1200);
    }).then(function(data){
      console.log(data);
    })
    

    不过我们知在一个then中 return 可能不仅仅是一个简单地的value , 有可能再次返回一个Promise对象 而下一个then中resolve函数的的data是这个Promise对象resolve()的值

    听起来很复杂 针对return一个Promise对象的情况 就是调用这个对象的then
    然后再次进入next 而next的参数就是返回的Promise对象的resolve的值

    function Promise(resolver) {
      var queue = []; //链式调用数组
      resolver(resolve, reject);
    
      //state 0 是resolve
      function next(state, val) {
        var arr;
        var chainRs;
        setTimeout(function() {
          if (arr = queue.shift()) {
            chainRs = arr[state](val);
            if(!chainRs) return;
            //某一个resolve函数返回的又是一个Promise对象
            if (chainRs && typeof chainRs.then == 'function') {
              chainRs.then(resolve, reject);
            } else {
              //resolve函数返回一个普通的值
              resolve(chainRs) //.then(resolve, reject);
            }
          }
        }, 0);
      }
    
      function resolve(x) {
        next(0, x);
      }
    
      function reject(reason) {
        next(1, reason);
      }
      //Promise最明显的特征 是可以then  then接收两个参数
      //then就是将传入的函数放入队列中
      this.then = function(resolve, reject) {
        queue.push([resolve, reject]); //resovle  reject  这两个参数也都是函数
        return this;
      }
    }
    Promise.resolve = Promise.cast = function(x) {
      return new Promise(function(resolve) {
        resolve(x);
      })
    }
    
    

    测试

    var p = new Promise(function(resolve) {
        setTimeout(function() {
          resolve('ok')
        }, 1200);
      }).then(function(data) {
        console.log(data);
        // return 555;
        return new Promise(function(resolve){
          setTimeout(function(){
            resolve('wahaha');
          }, 2200);
        })
      })
      .then(function(data) {
        console.log('2nd then', data);
        return 666;
      })
      .then(function(data) {
        console.log('3rd then', data);
      });
    

    完善 增加Promise.all() Promise.resolve()

    Promise.resolve = Promise.cast = function(x) {
      return new Promise(function(resolve) {
        resolve(x);
      })
    }
    
    Promise.all = function(promises){
      var len = promises.length;
      var results = [];
      return new Promise(function(resolve){
        promises.forEach(function(p, i){
          p.then(function(data){
              results[i] = data;
              len--;
              if(len == 0){
                resolve(results);
              }
          }, function(err){
            console.log(err);
          });
        });
      });
    }
    
    
    //=================================
    
    Promise.resolve(999)
    .then(function(data){
      console.log(data);
      return new Promise(function(resolve, reject){
        // resolve('xixi');
        reject('xixi');
      })
    }).then(function(data){
      console.log(data);
    },function(err){
      console.log(err);
    })
    
    Promise.all([
    new Promise(function(resolve){
      setTimeout(function(){
        resolve(111);
      }, 1000);
    
    }),
    new Promise(function(resolve){
      resolve(222);
    })
    
    ]).then(function(results){
      console.log(results);
    })
    
  • 相关阅读:
    HDU1875——畅通工程再续(最小生成树:Kruskal算法)
    CodeForces114E——Double Happiness(素数二次筛选)
    POJ3083——Children of the Candy Corn(DFS+BFS)
    POJ3687——Labeling Balls(反向建图+拓扑排序)
    SDUT2157——Greatest Number(STL二分查找)
    UVA548——Tree(中后序建树+DFS)
    HDU1312——Red and Black(DFS)
    生活碎碎念
    SQL基础四(例子)
    Linux系统中的一些重要的目录
  • 原文地址:https://www.cnblogs.com/cart55free99/p/5199630.html
Copyright © 2011-2022 走看看