Promise基本信息
什么是Promise
Promise是一门新的技术(ES6规范),是JS异步编程的新的解决方案(旧的方案是使用回调函数)
- 从语法上来说:Promise是一个构造函数
- 从功能上来说:promise对象用来封装一个一不糙做并且可以获取其成功失败的结果值
异步编程包括但不限于以下几种
- fs文件操作
require('fs').readFile('./index.html,(err,data)=>{}) - 数据库操作(Mongodb...)
- Ajax
$.get('/server',(data)=>{}) - 定时器
常用的实践练习加深理解
-
Promise实例化,参数是一个函数,参数是resolve和reject,参数内异步函数,然后成功执行resolve,失败执行reject。然后就调用Promise的then方法,来输出结果。
-
Promise实践练习-fs读取文件
-
Promise实践练习-AJAX请求
-
nodejs的util.promisify方法进行promise风格的封装
-
封装AJAX
Promise的状态改变
- pending变为resolved/fullfiled
- pending变为rejected 说明:只有这两种,而且一个promise对象只能改变一次,无论变为成功还是失败都只能改变一次,不能从失败转成功,或者从成功变失败
Promise对象中有一个属性叫做PromiseState,这个就是Promise对象的状态,那么这个属性有几种状态测存在呢?总共有一下三种:
pending未决定的resolved/fulfilled成功rejected失败
Promise的基本流程
为什么使用Promise
1.支持链式调用,可以解决回调地狱的问题
- 什么是回调地狱 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
- 回调地狱的缺点 不便于阅读,不便于异常处理 2.指定回调函数的方式更加灵活:回调函数的方式必须在启动异步任务之前制定,但是promise:启动异步任务=》返回promise对象=〉给promise对象绑定回调函数(甚至可以在异步任务结束后指定) 3.解决方案 Promise链式调用 4.终极解决方案
Promise常用API
-
Promise构造函数:Promise(excutor){}
- excutor函数:是执行器(resolve,reject)=>{}
- resolve函数:内部定义成时候我们调用的函数 valve=>{}
- reject函数:内部定义失败时候,我们调用的函数 reason=>{} 说明:excutor会在Promise内部立即同步调用,异步操作在执行器中执行
-
Promise.prototype.then方法(onResolved,onRejected)=>{}
- onResolved函数:成功的回调函数(valve)=>{}
- onRejected函数:失败的回调函数(reason)=>{} 说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的Promise对象
-
Promise.prototype.catch方法
- onRejected函数:失败的回调函数(reason)=>{}
-
Promise.resolve 方法:(valve)=>{}
- value:成功的数据或者promise对象,返回一个成功/失败的promise对象
- value:成功的数据或者promise对象,返回一个成功/失败的promise对象
-
Promise.reject函数 方法:(reason)=>{}, 无论你传入什么,字符还是promise对象,结果都是失败的
-
Promise.all 方法 (promises)=>{}
- promises:包含n个promise的数组,返回一个新的promise,只有所有的promise都成功才会成功,只要有一个失败了就直接失败
-
Promise.race 方法(promises)=>{}
- promises:包含n个promise的数组,返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态
由于p1先完成,所以结果就是p1的
肯定不是p1,应该是p2
Promise关键的问题
-
在代码中如何改变promise的状态
- 调用resolve函数,可以将状态pending=>fullfilled(resolved)
- 调用reject函数,可以将状态pending=>rejected
- throw抛出异常:如果当前是pending就会变成reject
-
一个promise指定多个成功/失败回调函数,都会调用吗? 在这里就是then()方法当promise改变为对应状态的时候就会调用,但是如果状态不变的话就不会调用,比如,我们注释掉下图中的resolve('OK')
-
改变状态和指定回调函数谁先谁后(也就是resolve/reject先执行,还是then先执行)
- 都有可能,正常情况下是先指定回调函数再改变状态,但是也可以先改变状态再指定回调函数,
- 如何先改变状态再指定回调(1)在执行器中直接调用resolve/reject函数(当执行器中的函数是同步函数的时候,就先改变状态resolve/reject,再执行回调then)(2) 延长更长时间才调用then(比如执行器中延长一秒执行resolve,但是可以设置2秒后再执行then)
- 什么时候才能得到数据,也就是回调函数什么时候执行(1)如果先指定的回调函数,那么当状态发生改变的时候,回调函数就会调用,得到数据,(2)如果先改变的状态,那么当指定回调函数时,回调函数就会调用,得到数据
-
Promise.then()返回新的promise的结果状态由什么决定
- 简单表达就是由then指定的回调函数执行的结果决定
- 详细表达就是(1)如果抛出异常,新promise变为reject,reason为抛出的异常(2)如果返回的是非promise的任意值,那么新promise变为resolved,value为返回的值,(3)如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
-
promise如果串联多个操作任务
- promise的then返回一个新的promise,可以开成then的链式调用
- 通过then链式调用串联多个同步/异步任务 image.png
-
Promise异常穿透
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 前面任何操作出了异常,都会传到最后失败的回调中处理
-
中断promise链
- 当使用promise的then链式调用时,在中间中断,不再调用后面的then方法多,有且只有一个方式,就是return一个pending的promise对象
- 当使用promise的then链式调用时,在中间中断,不再调用后面的then方法多,有且只有一个方式,就是return一个pending的promise对象
Promise自定义封装(手写Promise)
转发一篇手写promise文档:juejin.cn/post/699459…
async 和 await
async函数
-
函数的返回值为promise对象
-
promise对象的结果由async函数执行的返回值决定
await
-
await右侧的表达式一般为promise对象,但是也可以是其他的值
-
如果表达式是promise对象,await返回的就是promise成功的值
-
如果表达式是其他值,直接将此值作为await的返回值
注意:1.await必须卸载async函数中,但是async函数中可以没有await 2. 如果await的promise失败了,就会抛出异常,需要通过try..catch来捕获处理