promise

作者: 2018不下雪 | 来源:发表于2018-01-13 21:37 被阅读0次

    回调嵌套

    let fs = require('fs');
    fs.readFile('./template.txt', 'utf8', function (err, template) {
      fs.readFile('./data.txt', 'utf8', function (err, data) {
       console.log(template + ' ' + data);
      })
    })
    

    如果我们需要template中的数据,又需要data中的数据。 这样就会出现回调嵌套的问题。如果还有很多这样的请求,将会一层一层嵌套下去,这样代码将变得非常难看和难以维护。
    如何解决这个问题?

    promise的简单使用

    promise为承诺,承诺的是未来的事情。可能成功,也可能失败。

    let p1 = new Promise(function(resolve,reject){
      setTimeout(function(){
        resolve('成功');
      },1000);
    });
    p1.then(function(value){
      console.log('成功',value);
    },function(reason){
      console.log('失败',reason);
    });
    

    new一个promise的实例p1,传入一个函数,这个函数中有两个参数,resolve和reject这是两个方法,resolve为成功执行的方法,reject为失败执行的方法。

    promise原理分析

    简单实现promise

    先简单实现一个promise,然后逐步完善。
    Promise是一个构造函数,所以先创建一个构造函数。里面有resolve和reject两个方法。因为then方法是通过promise的实例调用的。在Promise的实例的原型上有一个then方法。

    //构造函数的参数是一个异步任务
    function Promise(task) {
      let that = this;//缓存this
      //默认状态为pending
      that.status = 'pending';
      //此变量里放着此promise的结果
      that.value = undefined;
      //存放的着所有成功的回调函数
      that.onResolvedCallbacks = [];
      //存放着所有的失败的回调函数
      that.onRejectedCallbacks = [];
      //调用此方法可以把promise变成成功态
      function resolve(value) {
        if (that.status == 'pending') {
          that.status = 'fulfilled';
          that.value = value;
          that.onResolvedCallbacks.forEach(item=>item(that.value));
        }
      }
    
      //调用此方法可以把当前的promise变成失败态
      function reject(reason) {
        //如果当前状态是初始态,则转成失败态
        if (that.status == 'pending') {
          that.status = 'rejected';
          that.value = reason;
          that.onRejectedCallbacks.forEach(item=>item(that.value));
        }
      }
    
      //立即执行传入的任务
      try {
        task(resolve, reject);
      } catch (e) {
        reject(e);
      }
    }
    //onFulfilled成功的回调,onReject失败的回调
    Promise.prototype.then = function (onFulfilled, onReject) {
      let that = this;
      if(that.status == 'fulfilled'){
        onFulfilled(that.value);
      }
      if(that.status == 'rejected'){
        onReject(that.value);
      }
      if(that.status == 'pending'){
        that.onResolvedCallbacks.push(onFulfilled);
        that.onRejectedCallbacks.push(onReject);
      }
    
    }
    
    module.exports = Promise;
    

    完善then方法

    //onFulfilled 是用来接收promise成功的值或者失败的原因
    Promise.prototype.then = function(onFulfilled,onRejected){
      //如果成功和失败的回调没有传,则表示这个then没有任何逻辑,只会把值往后抛
      onFulfilled = typeof onFulfilled == 'function'?onFulfilled:function(value){return  value};
      onRejected = typeof onRejected == 'function'?onRejected:reason=>{throw reason};
      //如果当前promise状态已经是成功态了,onFulfilled直接取值
      let self = this;
      let promise2;
      if(self.status == "fulfilled"){
        return promise2 = new Promise(function(resolve,reject){
          setTimeout(function(){
            try{
              let x =onFulfilled(self.value);
              resolvePromise(promise2,x,resolve,reject);
            }catch(e){
              //如果执行成功的回调过程中出错了,用错误原因把promise2 reject
              reject(e);
            }
          })
        });
      }
      if(self.status == "rejected"){
        return promise2 = new Promise(function(resolve,reject){
          setTimeout(function(){
            try{
              let x =onRejected(self.value);
              resolvePromise(promise2,x,resolve,reject);
            }catch(e){
              reject(e);
            }
          })
        });
      }
      if(self.status == "pending"){
       return promise2 = new Promise(function(resolve,reject){
         self.onResolvedCallbacks.push(function(){
             try{
               let x =onFulfilled(self.value);
               //如果获取到了返回值x,会走解析promise的过程
               resolvePromise(promise2,x,resolve,reject);
             }catch(e){
               reject(e);
             }
    
         });
         self.onRejectedCallbacks.push(function(){
             try{
               let x =onRejected(self.value);
               resolvePromise(promise2,x,resolve,reject);
             }catch(e){
               reject(e);
             }
         });
       });
      }
    }
    

    添加resolvePromise方法

    function resolvePromise(promise2,x,resolve,reject){
      if(promise2 === x){
        return reject(new TypeError('循环引用'));
      }
      let called = false;//promise2是否已经resolve 或reject了
      if(x instanceof Promise){
        if(x.status == "pending"){
          x.then(function(y){
            resolvePromise(promise2,y,resolve,reject);
          },reject);
        }else{
          x.then(resolve,reject);
        }
      //x是一个thenable对象或函数,只要有then方法的对象,
      }else if(x!= null &&((typeof x=='object')||(typeof x == 'function'))){
        //当我们的promise和别的promise进行交互
       try{
         let then = x.then;
         if(typeof then == 'function'){
           //有些promise会同时执行成功和失败的回调
           then.call(x,function(y){
             //如果promise2已经成功或失败了,则不会再处理了
              if(called)return;
              called = true;
              resolvePromise(promise2,y,resolve,reject)
           },function(err){
             if(called)return;
             called = true;
             reject(err);
           });
         }else{
           //到此的话x不是一个thenable对象,那直接把它当成值resolve promise2就可以了
           resolve(x);
         }
       }catch(e){
         if(called)return;
         called = true;
         reject(e);
       }
    
      }else{
        //如果X是一个普通 的值,则用x的值去resolve promise2
        resolve(x);
      }
    }
    

    Promise.all

    Promise.all = function(promises){
     return new Promise(function(resolve,reject){
       let done = gen(promises.length,resolve);
       for(let i=0;i<promises.length;i++){
         promises[i].then(function(data){
           done(i,data);
         },reject);
       }
     });
    }
    

    Promise.race

    Promise.race = function(promises){
      return new Promise(function(resolve,reject){
        for(let i=0;i<promises.length;i++){
          promises[i].then(resolve,reject);
        }
      });
    

    Promise.resolve

    Promise.resolve = function(value){
      return new Promise(function(resolve){
        resolve(value);
      });
    }
    

    Promise.reject

    Promise.reject = function(reason){
      return new Promise(function(resolve,reject){
        reject(reason);
      });
    }
    

    相关文章

      网友评论

          本文标题:promise

          本文链接:https://www.haomeiwen.com/subject/dochoxtx.html