Promise
· 3 min read
- What's Promise?
- Why the Promise?
- How using Promise?
#
Prepare#
函数对象与实例对象函数对象: 将函数作为对象使用时, 简称为函数对象
实例对象: new 函数产生的对象, 简称为对象
function Fn(){} // Fn函数
cosnt fn = new Fn() // Fn是构造函数 fn是实例对象(简称对象)console.log(Fn.prototype) // Fn是函数对象Fn.bind({}) // Fn是函数对象$('#test') // jQuery函数$.get('/test') // jQuery函数对象
#
回调函数的分类Callback function 自己定义,不用亲自调用(无法决定调用时间),会执行。
- 同步回调:
- 立即执行, 完全执行完了才结束, 不会放入回调队列中
- e.g.
- 数组遍历相关的回调函数
- Promise 的 excutor 函数
const arr = [1, 2, 5];// 遍历回调,同步回调函数,不会放入回调队列arr.forEach((item) => { console.log(item);});console.log("end"); // 1,2,5,end
- 异步回调:
- 不会立即执行,放入回调队列,所有同步执行完后才可能执行
- e.g.
- 定时器回调
- ajax 回调
- Promise 的成功|失败的回调
setTimeout(() => { console.log("timeout callback()");}, 0);console.log("end"); // end,timeout callback()
#
Promise 的理解和使用#
Promise 是什么?Promise 是 JS 中进行异步编程的新的解决方案(旧的 ☞ 纯回调机制)
Promise 是一个构造函数
promise 对象用来封装一个异步操作并可以获取其结果
promise 的状态改变(只有 2 种, 只能改变一次)
pending
变为resolved
返回的结果数据一般称value
pending
变为rejected
返回的结果数据一般称reason
promise 的基本流程
#
基本使用const p = new Promise((resolve, reject) => { // excutor function 执行异步操作 setTimeout(() => { const time = Date.now(); // 成功调用 resolve(value) if (time % 2 === 0) resolve("success,time=" + time); // 失败调用 reject(reason) else reject("fail,time=" + time); }, 1000);});
p.then( // onResolved (value) => { console.log("成功的回调", value); }, // onRejected (reason) => { console.log("失败的回调", reason); });
#
为什么要用 Promise?- 指定回调函数的方式更加灵活
- 纯回调:必须在异步任务之前指定回调函数,
- Promise:启动异步任务 => return promise object => bind callback function(甚至可以在异步任务结束后)
- 支持链式调用, 可以解决回调地狱问题
#
如何使用 Promise?- 主要 API
- Promise 构造函数: Promise (excutor) {}
- Promise.prototype.then 方法: (onResolved, onRejected) => {}
- Promise.prototype.catch 方法: (onRejected) => {}
- Promise.resolve 方法: (value) => {}
- Promise.reject 方法: (reason) => {}
- Promise.all 方法: ([promises]) => {}
- Promise.race 方法: ([promises]) => {}
- 几个重要问题
- 如何改变 promise 的状态?
- 一个 promise 指定多个成功/失败回调函数, 都会调用吗?
- promise.then()返回的新 promise 的结果状态由什么决定?
- 改变 promise 状态和指定回调函数(
then()
)谁先谁后? - promise 如何串连多个操作任务?
- promise 异常穿透?
- 中断 promise 链
#
自定义 Promise- 定义整体结构
- Promise 构造函数的实现
- promise.then()/catch()的实现
- Promise.resolve()/reject()的实现
- Promise.all/race()的实现
- Promise.resolveDelay()/rejectDelay()的实现(DIY 扩展)
- ES6 class 版本
#
代码https://github.com/zhang13pro/Promise-DIY
#
async 与 await#
async 函数- 函数的返回值为 promise 对象
- promise 对象的结果由 async 函数执行的返回值决定
#
await 表达式- await 右侧的表达式一般为 promise 对象, 但也可以是其它的值
- 如果表达式是 promise 对象, await 返回的是 promise 成功的值
- 如果表达式是其它值, 直接将此值作为 await 的返回值
#
注意:- await 必须写在 async 函数中, 但 async 函数中可以没有 await
- 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 来捕获处理
#
JS 异步之宏队列与微队列- 宏列队: 用来保存待执行的宏任务(回调), 比如: 定时器回调/DOM 事件回调/ajax 回调
- 微列队: 用来保存待执行的微任务(回调), 比如: promise 的回调/MutationObserver 的回调
- JS 执行时会区别这 2 个队列
- JS 引擎首先必须先执行所有的初始化同步任务代码
- 每次准备取出第一个宏任务执行前, 都要将所有的微任务一个一个取出来执行