promise是什么?
理解
抽象表达:
- Promise是一门新技术
Promise是JS异步编程的新方案 (之前采用回调函数就会造成回调地狱)
具体表达:
从语法来说:Promise 是一个构造函数
- 从功能上来说:Promise 对象用来封装一个异步操作并可以获取其成功/ 失败的结果值
Promise 基本原理
- Promise 是一个类,在执行这个类的时候会传入一个执行器,这个执行器会立即执行
- Promise 会有三种状态
- Pending 等待
- Fulfilled 完成
- Rejected 失败
- 状态只能由 Pending —> Fulfilled 或者 Pending —> Rejected,且一但发生改变便不可二次修改;
- Promise 中使用 resolve 和 reject 两个函数来更改状态;
- then 方法内部做但事情就是状态判断
- 如果状态是成功,调用成功回调函数
- 如果状态是失败,调用失败回调函数
Promise 使用情况
promise是用来解决两个问题的:
- 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步的问题,本身不能说promise是异步的
使用Promise基本api
- Promise构造函数: Promise (excutor) {}
excutor函数: 同步执行 (resolve, reject) => {}
resolve函数: 内部定义成功时我们调用的函数 value => {}
reject函数: 内部定义失败时我们调用的函数 reason => {}说明: excutor会在Promise内部立即同步回调,异步操作在执行器中执行 - Promise.prototype.then方法: (onResolved, onRejected) => {}
onResolved函数: 成功的回调函数 (value) => {}
onRejected函数: 失败的回调函数 (reason) => {}说明: 指定用于得到成功value的成功回调和用于得到失败reason的失败回调返回一个新的promise对象 - Promise.prototype.catch方法: (onRejected) => {}
onRejected函数: 失败的回调函数 (reason) => {}说明: then()的语法糖, 相当于: then(undefined, onRejected) - Promise.resolve方法: (value) => {}
value: 成功的数据或promise对象说明: 返回一个成功/失败的promise对象 - Promise.reject方法: (reason) => {}
reason: 失败的原因说明: 返回一个失败的promise对象 - Promise.all方法: (promises) => {}
promises: 包含n个promise的数组说明: 返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败 - Promise.race方法: (promises) => {}
promises: 包含n个promise的数组说明: 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
手写关键问题
1.如何改变promise的状态?
(1)resolve(value): 如果当前是pendding就会变为resolved
(2)reject(reason): 如果当前是pendding就会变为rejected
(3)抛出异常: 如果当前是pendding就会变为rejected
2.一个promise指定多个成功/失败回调函数, 都会调用吗?
当promise改变为对应状态时都会调用
const p = new Promise((resolve, reject) => {// resolve(1) // promise变为resolved成功状态// reject(2) // promise变为rejected失败状态// throw new Error('出错了') // 抛出异常, promse变为rejected失败状态, reason为 抛出的errorthrow 3 // 抛出异常, promse变为rejected失败状态, reason为 抛出的3})p.then(value => {},reason => {console.log('reason', reason)})p.then(value => {},reason => {console.log('reason2', reason)})
3.改变promise状态和指定回调函数谁先谁后?
- 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
- 如何先改状态再指定回调?
① 在执行器中直接调用resolve()/reject()
② 延迟更长时间才调用then() - 什么时候才能得到数据?
①如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
②如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
// 常规: 先指定回调函数, 后改变的状态new Promise((resolve, reject) => {setTimeout(() => {resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数}, 1000);}).then(// 先指定回调函数, 保存当前指定的回调函数value => {console.log('value', value)},reason => {console.log('reason', reason)})// 如何先改状态, 后指定回调函数new Promise((resolve, reject) => {resolve(1) // 先改变的状态(同时指定数据)}).then(// 后指定回调函数, 异步执行回调函数value => {console.log('value2', value)},reason => {console.log('reason2', reason)})console.log('-------')const p = new Promise((resolve, reject) => {setTimeout(() => {resolve(1) // 后改变的状态(同时指定数据), 异步执行回调函数}, 1000);})setTimeout(() => {p.then(value => {console.log('value3', value)},reason => {console.log('reason3', reason)})}, 1100);
4. promise.then()返回的新promise的结果状态由什么决定?
- 简单表达: 由then()指定的回调函数执行的结果决定
- 详细表达:
①如果抛出异常, 新promise变为rejected, reason为抛出的异常
②如果返回的是非promise的任意值, 新promise变为resolved, value为返回的值
③如果返回的是另一个新promise, 此promise的结果就会成为新promise的结果
new Promise((resolve, reject) => {// resolve(1)reject(1)}).then(value => {console.log('onResolved1()', value)// return 2// return Promise.resolve(3)// return Promise.reject(4)throw 5},reason => {console.log('onRejected1()', reason) //1// return 2// return Promise.resolve(3)// return Promise.reject(4)throw 5}).then(value => {console.log('onResolved2()', value)},reason => {console.log('onRejected2()', reason) //5})
5.then 链式操作的用法?
- promise的then()返回一个新的promise, 可以开成then()的链式调用
- 通过then的链式调用串连多个同步/异步任务
- 所以,从表面上看,Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的:
new Promise((resolve, reject) => {setTimeout(() => {console.log("执行任务1(异步)")resolve(1)}, 1000);}).then(value => {console.log('任务1的结果: ', value)console.log('执行任务2(同步)')return 2}).then(value => {console.log('任务2的结果:', value)return new Promise((resolve, reject) => {// 启动任务3(异步)setTimeout(() => {console.log('执行任务3(异步)')resolve(3)}, 1000);})}).then(value => {console.log('任务3的结果: ', value)})/* 输出为执行任务1(异步)任务1的结果: 1执行任务2(同步)任务2的结果: 2执行任务3(异步))任务3的结果: 3*/
6.promise异常传/穿透?
- 当使用promise的then链式调用时, 可以在最后指定失败的回调,
- 前面任何操作出了异常, 都会传到最后失败的回调中处理
7.中断promise链?
- 当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
- 办法: 在回调函数中返回一个pendding状态的promise对象
new Promise((resolve, reject) => {// resolve(1)reject(1)}).then(value => {console.log('onResolved1()', value)return 2},// reason => {throw reason}).then(value => {console.log('onResolved2()', value)return 3},reason => {throw reason}).then(value => {console.log('onResolved3()', value)},reason => Promise.reject(reason)).catch(reason => {console.log('onReejected1()', reason) //当前代码输出为 onReejected1() 1// throw reason// return Promise.reject(reason)return new Promise(() => {}) // 返回一个pending的promise 中断promise链}).then(value => {console.log('onResolved3()', value)},reason => {console.log('onReejected2()', reason)})/*如果promise为resolve(1) 输出为onResolved1() 1onResolved2() 2onResolved3() 3onResolved3() undefined*///如果promise为reject(1)//输出为 onReejected1() 1
