一、Promise定义
1、抽象表达
(1)Promise 是一门新的技术(ES6 规范);
(2)Promise 是 JS 中进行异步编程的新解决方案。
备注:旧方案是单纯使用回调函数,一个回调函数中嵌套另一个异步任务,层级太多导致不便于阅读,也不便于异步处理。
2.具体表达
(1)从语法上来说: Promise 是一个构造函数;
(2)从功能上来说: promise 对象用来封装一个异步操作并可以获取其成功/ 失败的结果值。
异步编程包括:fs文件操作、数据库操作、AJAX、定时器
二、为什么要用Promise
1.回调地狱的缺点
(1)缩进太多,不便于阅读;
(2)不便于异常处理;
2.Promise优点
(1)支持链式调用,可以解决回调地狱问题;
(2)指定回调函数的方式更加灵活;
旧方案:必须在启动异步任务之前指定回调函数
Promise:启动异步任务 -> 返回promise对象 -> 给promise对象绑定回调函数
三、Promise的状态
1.Promise的状态即实例对象中的一个属性:PromiseState
(1) pending 未决定的
(2) resolved / fullfilled 成功
(3) rejected 失败
2.promise的状态改变
(1)pending变为resolved
(2)pending变为rejected
说明: 只有这 2 种, 且一个 promise 对象只能改变一次。无论变为成功还是失败, 都会有一个结果数据。成功的结果数据一般称为 value, 失败的结果数据一般称为 reason
四、Promise对象的值
Promise对象的值即实例对象中的另一个属性:PromiseResult,保存着异步任务成功/失败的结果
五、Promise的工作流程
![6](/img/6.jpg)
六、Promise基本使用
(1)初体验
1 | <body> |
(2)fs模块
1 | const fs = require('fs'); |
(3)AJAX请求
1 | <body> |
(4)promise封装fs操作
1 | // 封装一个函数mineReadFile,读取文件内容 |
(5)until.promisify方法
1 | // util.promisify |
(6)promise封装AJAX
1 | <body> |
七、如何使用Promise
1.API
1.Promise 构造函数: Promise (excutor) {}
(1) executor 函数: 执行器 (resolve, reject) => {}
(2) resolve 函数: 内部定义成功时我们调用的函数 value => {}
(3) reject 函数: 内部定义失败时我们调用的函数 reason => {}
说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
2.Promise.prototype.then 方法: (onResolved, onRejected) => {}
(1) onResolved 函数: 成功的回调函数 (value) => {}
(2) onRejected 函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的 promise 对象
3.Promise.prototype.catch 方法: (onRejected) => {}
(1) onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)
4.Promise.resolve 方法: (value) => {}
(1) value: 成功的数据或 promise 对象
说明: 返回一个成功/失败的 promise 对象
1 | // 如果传入的参数为非Promise类型的对象,则返回的结果为成功Promise对象 |
5.Promise.reject 方法: (reason) => {}
(1) reason: 失败的原因
说明: 返回一个失败的 promise 对象
1 | // 无论传入什么参数(即便是成功的Promise对象),都返回一个失败的Promise对象 |
6.Promise.all方法法: (promises) => {}
(1) promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
1 | <body> |
7.Promise.race 方法: (promises) => {}
(1) promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
1 | <body> |
八、Promise关键问题
1.如何改变promise的状态
(1) resolve(value): 如果当前是 pending 就会变为 resolved
(2) reject(reason): 如果当前是 pending 就会变为 rejected
(3) 抛出异常: 如果当前是 pending 就会变为 rejected
1 | // Promise对象状态改变的方式 |
2.能否执行多回调
当 promise 改变为对应状态时都会调用
1 | let p = new Promise((resolve, reject) => { |
3.改变 promise 状态和指定回调函数谁先谁后
(1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
(2) 如何先改状态再指定回调?
① 在执行器中直接调用 resolve()/reject() (即执行器里的是同步任务)
② 延迟更长时间才调用 then()
(3) 什么时候才能得到数据?
① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
4.promise.then()返回的新 promise 的结果状态由什么决定?
(1) 简单表达: 由 then()指定的回调函数执行的结果决定
(2) 详细表达:
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
5.promise 如何串联多个操作任务
(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务
1 | let p = new Promise((resolve, reject) => { |
6.promise 异常穿透
(1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
(2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
7.中断promise链
(1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
(2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象
1 | let p = new Promise((resolve, reject) => { |
九、Promise自定义封装
index.html
1 |
|
promise.js
1 | function Promise(excutor) { |