美文网首页
Promise技术探究

Promise技术探究

作者: 常青_1f93 | 来源:发表于2018-01-13 23:35 被阅读0次

1.promise简介

  1.1    

          Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果。 什么时候会用到过一段时间?答案是异步操作,异步是指可能比较长时间才有结果的才做。

        Promise表示一个异步操作的最终结果。与Promise最主要的交互方法是通过将函数传入它的then方法从而获取得Promise最终的值或Promise最终最拒绝(reject)的原因。

1.2  Promise状态

一个Promise必须处在其中之一的状态:pending, fulfilled 或 rejected.

如果是pending状态,则promise:

可以转换到fulfilled或rejected状态。

如果是fulfilled状态,则promise:

不能转换成任何其它状态。

必须有一个值,且这个值不能被改变。

如果是rejected状态,则promise可以:

不能转换成任何其它状态。

必须有一个原因,且这个值不能被改变。

”值不能被改变”指的是其identity不能被改变,而不是指其成员内容不能被改变。

1.3 then 方法

一个Promise必须提供一个then方法来获取其值或原因。

Promise的then方法接受两个参数:

promise.then(onFulfilled, onRejected)

onFulfilled 和 onRejected 都是可选参数:如果onFulfilled不是一个函数,则忽略之。如果onRejected不是一个函数,则忽略之。

如果onFulfilled是一个函数:它必须在promise fulfilled后调用, 且promise的value为其第一个参数。

它不能在promise fulfilled前调用。不能被多次调用。

如果onRejected是一个函数,它必须在promise rejected后调用, 且promise的reason为其第一个参数。

它不能在promise rejected前调用。不能被多次调用。

onFulfilled 和 onRejected 只允许在 execution context 栈仅包含平台代码时运行. 

onFulfilled 和 onRejected 必须被当做函数调用 (i.e. 即函数体内的 this 为undefined). 

对于一个promise,它的then方法可以调用多次.

当promise fulfilled后,所有onFulfilled都必须按照其注册顺序执行。

当promise rejected后,所有OnRejected都必须按照其注册顺序执行。

then 必须返回一个promise 

promise2 = promise1.then(onFulfilled, onRejected);

如果onFulfilled 或 onRejected 返回了值x, 则执行Promise 解析流程[[Resolve]](promise2, x).

如果onFulfilled 或 onRejected抛出了异常e, 则promise2应当以e为reason被拒绝。

如果 onFulfilled 不是一个函数且promise1已经fulfilled,则promise2必须以promise1的值fulfilled.

如果 OnReject 不是一个函数且promise1已经rejected, 则promise2必须以相同的reason被拒绝.

2.使用promise

let promise = new Promise((resolve, reject) => {

        setTimeout(function(){

                let num =Math.random();

                  if(num<.5){

                        resolve(num);

                  }else{

                        reject('失败');

                  }

        })

});

promise.then(Fulfilled,Rejected)

构造一个Promise实例需要给Promise构造函数传入一个函数。

传入的函数需要有两个形参,两个形参都是function类型的参数。

第一个形参运行后会让Promise实例处于resolve状态,所以我们一般给第一个形参命名为resolve,使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作

第一个形参运行后会让Promise实例处于reject状态,所以我们一般给第一个形参命名为reject,将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作

3 .自己实现promise

const PENDING = 'pending';//初始态

const FULFILLED =  'fulfilled';//成功态

const REJECTED =  'rejected';//失败态

function Promise(executor){

  let self = this;//先缓存当前promise实例

  self.status = PENDING;//设置状态

  //定义存放成功的回调的数组

  self.onResolvedCallbacks = [];

  //定义存放失败回调的数组

  self.onRejectedCallbacks = [];

  //当调用此方法的时候,如果promise状态为pending,的话可以转成成功态,如果已经是成功态或者失败态了,则什么都不做

  function resolve(value){ 

    if(value!=null &&value.then&&typeof value.then == 'function'){

      return value.then(resolve,reject);

    }

    //如果是初始态,则转成成功态

    setTimeout(function(){

      if(self.status == PENDING){

        self.status = FULFILLED;

        self.value = value;//成功后会得到一个值,这个值不能改

        //调用所有成功的回调

        self.onResolvedCallbacks.forEach(cb=>cb(self.value));

      }

    })

  }

  function reject(reason){ 

    setTimeout(function(){

      //如果是初始态,则转成失败态

      if(self.status == PENDING){

        self.status = REJECTED;

        self.value = reason;//失败的原因给了value

        self.onRejectedCallbacks.forEach(cb=>cb(self.value));

      }

    });

  }

  try{

    //因为此函数执行可能会异常,所以需要捕获,如果出错了,需要用错误 对象reject

    executor(resolve,reject);

  }catch(e){

    //如果这函数执行失败了,则用失败的原因reject这个promise

    reject(e);

  };

}

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);

  }

}

//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);

          //如果获取到了返回值x,会走解析promise的过程

          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);

        }

    });

  });

  }

}

module.exports =Promise;

4 自己实现promise.all

function gen(times,cb){

  let result = [],count=0;

  return function(i,data){

    result[i] = data;

    if(++count==times){

      cb(result);

    }

  }

}

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);

                    }

         });

}

5. 自己实现 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);

              }

    });

}

6. 自己实现 Promise.resolve

Promise.resolve =function(value){

        return new Promise(function(resolve){

                resolve(value);

          });

}

7. 自己实现 Promise.resolve

Promise.reject =function(reason){

           return new Promise(function(resolve,reject){

                reject(reason);

          });

}

相关文章

  • Promise技术探究

    1.promise简介 1.1 Promise本意是承诺,在程序中的意思就是承诺我过一段时间后会给你一个结果...

  • 探究promise

    前言 大家都知道Promise是ES6的一个针对回调地狱的一种解决方案,我们可以用promise去封装异步请求,用...

  • Promise实现原理(附源码)

    本篇文章主要在于探究 Promise 的实现原理,带领大家一步一步实现一个 Promise , 不对其用法做说明,...

  • Promise的理解和使用

    Promise是什么? 理解 1. 抽象表达 Promise是一门新的技术(ES6规范) Promise是JS中进...

  • 探究promise的真实面貌

    这篇文章的目的就是想探索一下promise是怎么实现的,因为promise一直在用,但是对于它内部具体是怎么实现的...

  • 关于Promise (草稿)

    Promise作为一重要的前端技术是所有大公司的面试必考技术点。下面做一简单介绍。 Promise是什么? 为什么...

  • setTimeout、setInterval被遗忘的第三个参数

    一、最近在看promise,惊奇的发现:原来 setTimeout不只有两个参数,我还能说什么呢?赶紧探探究竟。 ...

  • JavaScript中Promise函数then的奥秘探究

    Promise概述 Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口。 那么...

  • 探究JS中Promise函数then的奥秘

    Promise概述 Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口。 那么...

  • 探究Hybrid-APP技术原理

    探究Hybrid-APP技术原理author: @TiffanysBear 背景 随着Web技术的发展和移动互联网...

网友评论

      本文标题:Promise技术探究

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