在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现,但是这样的做法往往让代码,与思维进入了回调地狱当中;
function after(times,callback){ return function(obj){ if(--times===0){ callback(obj) } } }复制代码
在相当复杂的代码中如何回避回调地狱这种情况的,Promise模式也许是一个不错,可以使异步代码看起来如同步般清新易读,从而从回调地狱中解脱出来,ES6中 已原生支持 Promise,自然而然promise也有了他的一套规范;
rules
rules
- 1.new Promise时需要传递一个executor执行器,执行器会立刻执行
- 2.执行器中传递了两个参数 resolve成功的函数 他调用时可以传一个值 值可以是任何值 reject失败的函数 他调用时可以传一个值 值可以是任何值
- 3.只能从pending态转到成功或者失败
- 4.promise实例。每个实例都有一个then方法,这个方法传递两个参数,一个是成功另一个是失败
- 5.如果调用then时 发现已经成功了 会让成功函数执行并且把成功的内容当作参数传递到函数中
- 6.promise 中可以同一个实例then多次,如果状态是pengding 需要将函数存放起来 等待状态确定后 在依次将对应的函数执行 (发布订阅)
一个Promise存在三种状态
- pending: 初始状态
- resolve: 可以理解为成功
- reject: 可以理解为失败
Analysis Promise
首先我们来看原生如何调用Promise
new Promise((resolve,reject)=>{});复制代码
这里我们可以看出再调用构造函数时,其实传递了一个执行器
如果我们自己该怎样去实现这个流程.
rule.1
function Promise(executor){ function resolve(){ } function reject(){ } executor(resolve,reject) }复制代码
我们再看看rule.2不论是失败还是成功的情况,都会传递一个值,再结合rule3,我们可以预先给定一个预状态
function Promise(executor){ let _this=this; _this.status='pending'; _this.value='undefined'; _this.reason='undefined'; function resolve(value){ if( _this.status==='pending'){ _this.status='resolved'; _this.value=value; } } function reject(reason){ if(_this.status==='pending'){ _this.status='rejected'; _this.value=value; } } executor(resolve,reject) } 复制代码
接下来我们看看rule4,每一个promise实例,都应该有一个then方法并且可以传递两个参数,一个成功,一个失败,并且返回一个promise实例
function Promise(executor){...}; Promise.prototype.then=function(onfulfilled,onrejected){ //这里应该还应该处理为传递参数的情况 onfilfulled=typeof onfilfulled==='function?onfilfulled:val=>val; onrejected=typeof onrejected==='function?onrejected:val=>{throw val}; let promise2=new Promise((resolve,reject)=>{ ....... }) return promise2 }复制代码
我们做个假设如果resolve是异步的,情况又该如何处理;我觉得应该先把存储起来,然后异步调用
function Promise(executor){ .... let _this=this; _this.onResolves=[]; _this.onRejects=[]; ... _this.onRejects.forEach(fn=>fn()) ... ... _this.onResolves.forEach(fn=>fn()) .... } 复制代码
如果我们的resolve是一个promise那么我们就还应该进一步解析,所以应该定义一个方法来处理这种情况
function resolvePromise(promise2, x, resolve, reject) { ......}复制代码