网站首页 > 技术文章 正文
Promise的作用
它是异步编程的一种方式,它比传统的异步回调和事件更合理也更优雅!
从Promise的使用中能看出什么?
首先我们手写一个常见的使用方式
//demo1 new Promise(function (resolve, reject) { resolve('123') }).then(function (value) { return value; }).then(function (value1) { return value1; }).catch(function(e) { return e; })
从这个demo中就可以看出来,首先需要定义一个Promise的构造函数、then方法以及catch方法。then方法可以传入两个函数作为参数,catch就是then演变而来的(第一个参数传null)。Promise的构造函数有一个函数作为参数,这个函数也有两个参数(resolve,reject)并且它们俩也是函数。
//demo2 Promise = function(fn) { fn(relsove, reject) } relsove = function(val) { } reject = function(val) { } Promise.prototype.then = function(fn1, fn2){ //fn1 和 fn2都是函数 } Promise.prototype.catch = function(fn){ this.then(null, fn) }
以上这段代码从使用promise的表面就能看出来。
Promise链式调用
我们把demo1换一种书写的形式
//demo3 p1 = new Promise(function (resolve, reject) { resolve('123') }) p2 = p1.then(function (value) { return value; }) p3 = p2.then(function (value1) { return value1; }) p4 = p3.catch(function(e) { return e; })
从上面的代码中可以看出来,Promise采用链式调用,类似于jquery,无论then还是catch肯定都返回一个promise对象,那么p1、p2、p3、p4返回的promise对象是同一个吗?并不是!!!每次调用then方法都会返回一个新的promise对象。
//demo4 noop = function() { } Promise.prototype.then = function(fn1, fn2){ return new this.constructor(noop) }
Promise对象的状态
promise对象存在三种状态
- 未执行
- 执行完成,此处又分两种
//demo5 PENDING = 0 //未执行 FULFILLED = 1 //执行完毕,符合预期 REJECTED = 2 //执行完毕,不符合预期 p.state = 0/1/2
Promise链式调用的结果传递
看demo3,除了p1初始化一个promise对象外,p2、p3、p4都各自生成了一个promise对象,每个promise对象除了挂载一个运行状态外,还挂载运行结果、下一个promise对象,以及then中的两个参数函数。
//demo6 p.state //运行状态 p.result //运行结果 p.subscribers = [child, fn1, fn2] //child 是下一个then生成的promise对象 //fn1 和 fn2 是下一个then的两个参数,catch中fn1=null child.state //运行状态 child.result //运行结果 child.subscribers = [child1, fn1, fn2]
可以想到只要上一个promise运行完成,就能拿到上一个promise的运行结果和运行状态,就能传给下一级,subscribers会根据上一个promise的运行状态来选择运行fn1还是fn2,然后把上一个promise的运行结果传递给它们其中一个。最后待完成之后,又会通过child寻找下一个child,一层层找下去。
Promise链式调用中出现异常
修改demo3
//demo7 p1 = new Promise(function (resolve, reject) { reject(123) }) p2 = p1.then(function (value) { return value; }) p3 = p2.then(function (value1) { return value1; }) p4 = p3.catch(function(e) { return e+1; }) p5 = p4.catch(function(value2) { return value2; })
我们一般提倡不写then的第二个函数,下面接catch方法,这样看起来更优雅
p1运行后的状态是2,但是p2中的then方法没有第二参数函数,这样的情况是p2的状态和运行结果会被设置为和p1一致,p3也没有第二个参数,它也会跟随p2的状态,直到catch。
//demo8 p1.state = 2 p1.result = 123 p2.state = 2 p2.result = 123 p3.state = 2 p3.result = 123 p4.state = 1 p4.result = 123 p5.state = 1 p5.result = 124
运行catch的时候,结果符合预期没有发生异常,所以呢,这个p4的状态又变成了1,下面的p5肯定也是1,之前的p2、p3中的状态和结果会和它们的上一级保持一致,虽然它们的then方法的第一个参数没有运行。
为什么Promsie中异步的情况下链式也能正常执行
看demo1
1、无论是new一个promise对象还是后面执行then和catch方法都是同步的,它们都是在做初始化的工作;
2、其中重要的就是每次运行一个then都会创建一个新的promise对象作为上一个promise对象的child,上一个promise对象作为parent,而child是否挂载到parent上作为它的一个属性取决于创建child的时候parent的状态state还是不是为0,如果parent已经运行完成,状态变成了1或者2,child可以直接拿到parent的结果,那么就不需要把child挂载到parent上,反之需要!
3、当开关->parent->child->child->.....这样的链路建立以后,无论什么时候打开开关,它都会像多米诺骨牌一样向后依次执行,而resolve/reject就是这个开关
为什么Promise中能抓住异常并把异常传递到catch中处理
无论是promise构造函数中参数函数,还是then中的参数函数,它们都是在一个try catch中执行的,catch中会用reject处理
//demo9 Promise = function(fn) { try { fn(relsove, reject) } catch(e) { reject(e) } } relsove = function(val) { } reject = function(val) { } Promise.prototype.then = function(fn1, fn2){ //fn1 和 fn2都是函数 try { fn12(value) } catch(e) { reject(e) } }
异步中的异常是抓不住的!
总结
本来想写全的,但是发现越写东西越多,这篇文章就分析到这吧,后面再补充!很多东西讲浅了怕说的不全面,讲深了又怕描述不清楚!
喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!
- 上一篇: 「ES6基础」Object的新方法
- 下一篇: web前端之“神秘”的跨域方式 web前端跨域问题
猜你喜欢
- 2025-05-26 ES6字符串的新特性及新增方法梳理
- 2025-05-26 ES6新增语法(七)——async...await
- 2024-09-24 「ES6基础」Object的新方法
- 2024-09-24 「ES6基础」const的用法
- 2024-09-24 「ES6基础」箭头函数(Arrow functions)
- 2024-09-24 前端关于ES6的面试题汇总含答案
- 2024-09-24 前端系列——ES6中的数据结构map和set
- 2024-09-24 前端ES6数组方法总结
- 2024-09-24 前端ES6中Promise的运行原理之进阶篇(一)
- 2024-09-24 写给前端的你:ES6模块化知识点总结
你 发表评论:
欢迎- 05-30为什么说网上的md5加密解密站都是通过彩虹表解密的?
- 05-30一文读懂md5,md5有什么用,什么是md5加盐
- 05-30Java md5加密解密数据
- 05-30MD5是什么?如何进行MD5校验?
- 05-30专家教你简单又轻松的MD5解密方法,一看就会
- 05-30多学习才能多赚钱之:vscode怎么安装插件
- 05-30VSCode无限画布模式(可能会惊艳到你的一个小功能)
- 05-30VSCode神级Ai插件Cline:从安装到实战【创建微信小程序扫雷】
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)