博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深度解析利用ES6进行Promise封装总结
阅读量:6437 次
发布时间:2019-06-23

本文共 6668 字,大约阅读时间需要 22 分钟。

这篇文章主要介绍了如何利用ES6进行Promise封装总结,文中通过示例代码介绍的非常详细,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下。如有不足之处,欢迎批评指正。

原生Promise解析

简介

  • promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和强大。
  • promise简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,从语法上来说,Promise是一个对象,从它可以获取异步操作的消息,Promise提供统一的API,各种异步操作都可以用同样的方法进行处理

特点

对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:Pendding、fulfilled、rejected。只有异步操作的结果,可以决定当前是哪一种状态,其他操作都无法改变这个状态。

一旦状态改变,就不会在变,任何时候都可以得到这个结果,只有两种可能:从Pendding变为fulfilled和从Pendding变为rejected。只要这两种情况发生,状态就凝固了,会一直保持这个结果,这时就称为resolved。
1.利用es6进行Promise封装

2.处理同步任务

3.原生方法调用方式

new Promise((resolve,reject)=>{  resolve(1)}).then(res=>{  console.log(res) //1})

同步封装思考

1.由调用方式可见Promise是一个类
2.它接收一个回调函数,这个回调函数接受resolve和reject方法作为参数
3.当状态改变后执行then方法,并将resolve或reject的结果作为then方法接受回调函数的参数

class Mypromise{  constructor(callback){    this.status='pendding'    //成功结果    this.s_res = null    // 失败结果    this.f_res = null    callback((arg)=>{ // 使用箭头函数this不会丢失     // 改变状态为成功     this.status = 'fulfilled'     this.s_res = arg    },(arg)=>{      // 改变状态为失败      this.status = 'rejected'      this.f_res = arg     })  }  then(onresolve,onreject){    if(this.status === 'fulfilled'){ // 当状态为成功时      onresolve(this.s_res)    }else if(this.status === 'rejected'){ // 当状态为失败时      onreject(this.f_res)    }//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力  }}

处理异步任务

原生调用方式

new Promise((resolve,reject)=>{  setTimeOut(()=>{    resolve(1)  },1000)}).then(res=>{  console.log(res)})

异步封装思考

1.根据js执行机制,setTimeOut属于宏任务,then回调函数属于微任务,当主线程执行完成后,会从异步队列中取出本次的微任务先执行。
2.也就是说,then方法执行时,状态还没有改变,所有我们需要将then方法执行的回调保存起来,等到异步代码执行完成后,在统一执行then方法的回调函数

class Mypromise{  constructor(callback){    this.status='pendding'    //成功结果    this.s_res = null    // 失败结果    this.f_res = null    this.query = [] // ++     callback((arg)=>{ // 使用箭头函数this不会丢失     // 改变状态为成功     this.status = 'fulfilled'     this.s_res = arg     // 当状态改变后,统一执行then方法的回调     this.query.forEach(item=>{       item.resolve(arg)     })//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力    },(arg)=>{      // 改变状态为失败      this.status = 'rejected'      this.f_res = arg       // 当状态改变后,统一执行then方法的回调     this.query.forEach(item=>{       item.reject(arg)     })    })  }  then(onresolve,onreject){    if(this.status === 'fulfilled'){ // 当状态为成功时      onresolve(this.s_res)    }else if(this.status === 'rejected'){ // 当状态为失败时      onreject(this.f_res)    }else{ // ++ 状态没有改变      this.query.push({ // 保存回调函数到队列中        resolve:onresolve,        reject:onreject      })//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力    }  }}

处理链式调用

原生调用方式

new Promise((resolve,reject)=>{  resolve(1)}).then(res=>{  return res}).then(res=>{  console.log(res)})//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力

链式调用思考

原生的Promise对象的then方法,返回的也是一个Promise对象,一个新的Promise才能支持链式调用

下一个then方法可以接受上一个then方法的返回值作为回调函数的参数
主要考虑上一个then方法的返回值:
1.Promise对象/具有then方法的对象
2.其他值
第一个then方法返回一个Promise对象,它的回调函数接受resFn和rejFN两个回调函数作为参数,把成功状态的处理封装为handle函数,接受成功的结果作为参数
在handle函数,根据onresolve返回值的不同做出不同的处理

class Mypromise{  constructor(callback){    this.status='pendding'    //成功结果    this.s_res = null    // 失败结果    this.f_res = null    this.query = [] // ++     callback((arg)=>{ // 使用箭头函数this不会丢失     // 改变状态为成功     this.status = 'fulfilled'     this.s_res = arg     // 当状态改变后,统一执行then方法的回调     this.query.forEach(item=>{       item.resolve(arg)     })    },(arg)=>{      // 改变状态为失败      this.status = 'rejected'      this.f_res = arg       // 当状态改变后,统一执行then方法的回调     this.query.forEach(item=>{       item.reject(arg)     })    })  }  then(onresolve,onreject){    return new Mypromise((resFN,rejFN)=>{      if(this.status === 'fulfilled'){ // 当状态为成功时        handle(this.s_res)      }else if(this.status === 'rejected'){ // 当状态为失败时        errBack(this.f_res)      }else{ // ++ 状态没有改变        this.query.push({ // 保存回调函数到队列中          resolve:onresolve,          reject:onreject        })      } //在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力      function handle(value){        // 当then方法的onresolve方法有返回值时,保存其返回值,没有使用其保存的值        let returnVal = onresolve instanceof Function && onresolve(value) || value        // 如果onresolve方法返回的是promise对象,则调用其then方法        if(returnVal&&returnVal['then'] instanceof Function){          returnVal.then(res=>{            resFN(res)          },err=>{            rejFN(err)          })        }else{          resFN(returnVal)        }       }      function errBack(reason){        if(onreject instanceof Function){          let returnVal = reject(reason)          if(typeof returnVal !== 'undenfined' && returnVal['then'] instanceof Function){            returnVal.then(res=>{              resFN(res)            },err=>{              rejFN(err)            })          }else{            resFN(returnVal)          }        }else{          rejFN(reason)        }      }    })  }}

Promise.all和Promise.race方法

原生调用方式

Promise.all方法接受一个数组,数组中的每一项都是一个Promise实例,只有数组中的所有Promise实例的状态都变为fulfilled时,此时整个状态才会变成fulfilled,此时数组中所有Promise实例的返回值组成一个新的数组,进行传递。
Promise.race方法和Promise.all方法一样,如果不是Promise实例,就会先调用Promise.resolve方法,将参数转为Promise实例,在进行下一步处理。
只要数组中有一个参数的状态变为fulfilled就会进行传递

// 将现有对象转换为Promise对象  Mypromise.resolve = (arg)=>{    if(typeof arg == 'undefined' || arg==null){ // 不带有任何参数      return new Mypromise(resolve=>{        resolve(arg)      })    }else if(arg instanceof Mypromise){ // 是一个Mypromise实例      return arg    }else if(arg['then'] instanceof Function){ // 具有then方法的对象      return new Mypromise((resolve,reject)=>{        arg.then(res=>{          resolve(res)        },err=>{          reject(err)        })//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力      })    }else{ // 参数不是具有then方法的对象,或根本不是对象      return new Mypromise(resolve=>{        resolve(arg)      })     }  }  Mypromise.all = (arr)=>{    if(!Array.isArray(arr)){      throw new TypeError('参数必须是一个数组')    }    return new Mypromise((resolve,reject)=>{      let i=0,result=[]      next()      functon next(){        // 如果不是Mypromise实例需要转换        Mypromise.resolve(arr[i]).then(res=>{          result.push(res)          i++          if(i===arr.length){            resolve(result)          }else{            next()          }        },reject)      }    })  }//在此我向大家推荐一个前端全栈开发交流圈:619586920  突破技术瓶颈,提升思维能力  Mypromise.race = (arr)=>{    if(!Array.isArray(arr)){      throw new TypeError('参数必须是一个数组')    }    return new Mypromise((resolve,reject)=>{      let done = false      arr.forEach(item=>{        Mypromise.resolve(item).then(res=>{          if(!done){            resolve(res)            done = true          }        },err=>{          if(!done){            reject(res)            done = true          }        })      })    })  }
处理Mypromise状态确定不能改变的特性
在重写callback中的resolve和reject方法执行前,先判断状态是否为'pendding'

结语

感谢您的观看,如有不足之处,欢迎批评指正。

转载地址:http://mikwo.baihongyu.com/

你可能感兴趣的文章
R语言实战(七)图形进阶
查看>>
Linux下配置安装PHP环境
查看>>
JDBC删除数据
查看>>
linux环境下vim创建java文件,并编译运行
查看>>
DOM基本操作(二:对节点的操作)
查看>>
QGridLayout比例
查看>>
JAVA作业(6)
查看>>
什么是ORM?
查看>>
Python 进程与线程小随笔
查看>>
Kung fu
查看>>
分布式事务参考
查看>>
Daily scrum[2013.12.07]
查看>>
【转】学习笔记:GoogLeNet
查看>>
基于HTML5的WebGL呈现A星算法的3D可视化
查看>>
activiti 工作流 动态 设置 指定 节点任务人、责任人、组 的实现方式
查看>>
第二类斯特林数入门
查看>>
H5页面关于android软键盘弹出顶起底部元素的解决方案
查看>>
Perl 教学 Perl5中的引用(指针)
查看>>
Objective-C中的继承
查看>>
基尼系数
查看>>