promise 出来已久,以前一直使用,没有仔细剖析原理,最近在复习es6的知识,写一下自己对于promise的理解。

  promise是es6的一种异步编程解决方案,避免频繁的回调函数,增强代码的可阅读性。

  写法很简单:   

    let p2 = new Promise((reslove, reject) => {reslove(1)})console.log(p2.then(res => {alert(res)}))

  Promise是内置的构造函数,reslove、reject是固定的,只能这么写。reslove()表示成功,reject()表示失败。

  方法:

  1. then()   then是Promise的核心方法,是用来获取异步的返回结果。有两个参数用来获取reslove 或 reject 的值。
  2. catch()  用来捕获异常。
  3. all() 多个promise,所有的参与的promise对象全部执行完才会出结果。参数为类数组对象。
  4. race() 参数为类数组对象,任何一个参与的promise对象执行完,就会出结果。

  以上为常用的四个方法。

  代码:

  

/***   promise*   异步编程的一种解决方案。** */const promise = new Promise(function (reslove, reject) {console.log('开始')setTimeout(function () {reslove(2)}, 3000)})promise.then(function (value) {return 3;}).then(function (value) {})//let p = new Promise((reslove, reject) => {setTimeout(()=>{let a = Math.random();if (a>0.5) {//reslove(a); // 这里说白了是就是调用下面的then中的函数 areslove.call(null, a) // 这样也行} else {reject(a) // 调用b}reject(a) // 调用b}, 1000)})p.then(res => { // 假设这是函数areturn res;}, rej => { // 函数breturn rej;}).then(success => { // 链式调用的重点是前边的then必须return 否则 为undefinedreturn success;}, fail => {return fail;})// then() then方法是挂在Promise.prototype上的console.log(Promise.prototype) // Promise {constructor: ƒ, then: ƒ, catch: ƒ, finally: ƒ, Symbol(Symbol.toStringTag): "Promise"}// catch() 相当于 then(null, reject)p.then(rel => {console.log(rel)return rel;},rej => {console.log(rej + '小')return rej;}).then(rel => { // 前一个then返回成功或失败都在这里  因为执行catch()后返回一个新的实例该实例该实例执行完之后会变为reslove ,因此后边的catch始终执行不到console.log(rel)alert(2)}).catch(rej => { // 这句是走不到的console.log(rej)alert(1)console.log('二小')})// finally() 状态成功或失败 都会执行此操作let p1 = new Promise((reslove, reject) => {console.log(this) // window 箭头函数本身没有this 因此this指向定义箭头函数时的上下文reslove(1);})p1.then(res => {console.log('success')}).finally(res => {console.log('finally')})// all() 所有实例的状态都改变完才改变let p2 = new Promise((reslove, reject) => {setTimeout(() => {alert(1)reslove(1)} ,1000)})let p3 = new Promise((reslove, reject) => {setTimeout(() => {alert(2)reslove(2)} ,2000)})let p4 = new Promise((reslove, reject) => {setTimeout(() => {alert(3)reject(3)} ,3000)})Promise.all([p2, p3]).then(res => {console.log(res) // [1, 2]})Promise.all([p2, p3, p4]).then(res => {console.log(res)}).catch(rej => {console.log(rej) // 3  只要有一个reject 就走这里 不走上边的then 返回的永远是第一个reject的promise实例})// race()Promise.race([p2, p3]).then(res => {console.log(res) // 1})

  下面是手写的实现promise的原理:

  

// 实现 promisefunction MyPromise(fn){ // fn 为 new Promise(fn)let _this = this;_this.status = 'pending';_this.resloveValue = null; // 成功时的数据_this.rejectValue = null; // 失败时的数据_this.resloveFnCallbacks = [];_this.rejectFnCallbacks = [];function reslove(value) {if (_this.status == 'pending') {_this.status = 'resloved';_this.resloveValue = value;_this.resloveFnCallbacks.forEach(fn => fn())}}function reject(value) {if (_this.status == 'pending') {_this.status = 'rejected';_this.rejectValue = value;_this.rejectFnCallbacks.forEach(fn => fn())}}// 捕获异常try{fn(reslove, reject)} catch (e) {reject(e)}}// then() 应该接受两个参数 成功 或 失败的 回调MyPromise.prototype.then = function (resloveFn, rejectFn) {let _this = this;let promise2; // then 返回的promise// 参数非函数转为函数resloveFn = typeof resloveFn === 'function'? resloveFn: (function (value) {return value;})rejectFn = typeof rejectFn === 'function'? rejectFn: function (err) {throw err;}if(this.status == 'resloved') { // 成功alert(3)promise2 =  new MyPromise((reslove, reject) => {setTimeout(() => {let x = resloveFn(this.resloveValue);resolvePromise(promise2, x, reslove, reject);})})}if(this.status == 'rejected') { // 失败rejectFn(this.rejectValue)}if (this.status == 'pending') {this.resloveFnCallbacks.push(function(){resloveFn(_this.resloveValue)})this.rejectFnCallbacks.push(function(){rejectFn(_this.rejectValue)})}return promise2;// resolvePromisefunction resolvePromise(promise2, x, reslove, reject) {let called; // 是否调用过// 判断上一次then返回的值 实质上下一个then只需要一个值便可以,所以我们就是要将上一个的peomise中的值提取出来// then 返回promise只是为了链式调用,then本身需要一个实际的值,并不需要promiseif (x != null && (typeof x === 'object' || typeof x === 'function')) {try {let then = x.then; // 保存x的then方法 这种是x是对象if (typeof then === 'function') {then.call(x, function (y) {if (called) return;called = true;resolvePromise(promise2, y, reslove, reject)}, function (rej) {if (called) return;called = true;reject(rej)})} else { // x 是普通对象直接返回就行reslove(x);}} catch (e) {if (called) return;called = true;reject(e)}} else { // x 是普通值reslove(x)}}}// 将promiselet p6 = new MyPromise(function(reslove, reject) {reslove(2)})p6.then(function(res){return res;}).then(function(res){alert(res)})

  参考链接:https://juejin.im/post/5ab20c58f265da23a228fe0f

 

转载于:https://www.cnblogs.com/mzqn/p/8665173.html

道可道,非常道——详解promise相关推荐

  1. 详解promise、async和await的执行顺序

    说明: 本文摘自 详解 promise.async和await的执行顺序. 1.题目和答案 一道题题目:下面这段promise.async和await代码,请问控制台打印的顺序? async func ...

  2. 详解Promise使用与原理

    详解Promise使用与原理 一:Promise的概念 二:Promise的生命周期 三:如何让创建一个Promise 四:编写Promise结果处理程序 浅的讲差不多了,深的来了 --> .t ...

  3. 正则表达式-贪婪与非贪婪详解

    贪婪与非贪婪详解 正则的贪婪和非贪婪: 贪婪:当我们使用正则去匹配一个字符串的时候,它会尽可能多的去捕获内容,这个就是正则的贪婪 非贪婪::当我们使用正则去匹配一个字符串的时候,它会尽可能少的去捕获内 ...

  4. 【JAVA笔记——道】对象生命周期详解

    JAVA对象实例化过程 Class初始化理解 此篇中详细介绍了JAVA对象的实例化过程 JAVA对象内存分配过程 JVM 这里默认使用HotSpot虚拟机.简单回顾一下JVM内存结构,JVM中主要将使 ...

  5. python测试之道进阶,Pytest-Mock 进阶用法详解

    一.什么是 Mock 测试? Mock测试就是在 测试过程 中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法.这个虚拟的对象就是Mock对象.Mock对象就是真实对 ...

  6. 【禅道的使用】软件测试管理工具-禅道(思维导图详解)

    禅道的使用 一.禅道简介 测试管理工具-禅道(需求.用例.bug) bug管理工具-jira/QC/bug free/martins(bug) 二.禅道的下载和安装  B/S 1:下载:选择集成环境版 ...

  7. DevOps敏捷测试之道(全栈最详解)

    DevOps敏捷测试之道 目录 DevOps敏捷测试之道 背景:云测 CloudTest 敏捷和DevOps 测试债务 测试的焦点:业务价值的质量 自动化测试金字塔 常规安全与弹性安全 测试左移和测试 ...

  8. 技术转管理的成功率不到70%!你必须先迈过这9道坎...10页PPT详解

    来源| CSDN学院 && 技术领导力 整理| Emma 导读:曾经看到过一个数据,技术转管理的成功率不到7成,也就是说好不容易在职场中拼杀突围,获得了晋升机会,10个人里至少有3 个 ...

  9. Java 岗位 100道 面试题及答案详解

    详情解答 1:Arraylist和Linkedlist的区别? ArrayList.LinkedList.Vector和Stack是List的四个实现类,其中Vector是基于JDK1.0,虽然实现了 ...

最新文章

  1. PDOStatement 类 FETCH_* 系列
  2. Xftp使用教程——问答方式
  3. 统计学---数据的标准化
  4. idea启动多个tomcat失败
  5. 生产企业开具加工费发票的问题
  6. python面试题库——3数据库和缓存
  7. solverstate的使用
  8. 【HihoCoder - 1550】顺序三元组(思维)
  9. python php ajax赔率,Ajax如何调用python脚本
  10. centos7和scientific linux7里面调出中文输入法
  11. 大型网站的数据库分割问题。
  12. android导入项目j,如何使用AndroidStudio将开源项目library发布到jcenter
  13. 1000道Python题库系列分享15(1道代码改写题)
  14. hiho一下 第六十六周
  15. 计算学习理论、统计学习基础理论
  16. Java基础练习之流程控制(四)
  17. 利用构造函数实现累加
  18. (PDF格式论文加书签)Tampermonkey + 知网下载助手 + FreePic2Pdf
  19. 程序员做饭指南,GitHub教程来了
  20. 2021父亲节祝福话语、海报素材大全

热门文章

  1. 加速器,陀螺仪测量移动距离的方法
  2. 技巧篇:常用的R代码汇总
  3. iview在table中添加图片
  4. Linux 使用ffmpeg修改和压缩视频文件格式
  5. Esp8266 进阶之路25【高级篇】深聊下esp8266的串口 Uart 通讯中断编程,为您准备好了 NONOS 版本 和 RTOS 系统的串口驱动文件。(附带Demo)
  6. 在亚马逊网上注册kindle 3及下载免费电子图书的步骤
  7. Win10踩坑-开机0xc0000225
  8. 利用python制作马赛克图
  9. 【计算机网络】第一章--计算机网络概述
  10. qq邮箱smtp服务器imap,如何配置电子邮件客户端使用IMAP(QQ邮箱账户) 你需要学习了...