前期准备
回调函数
同步回调函数
理解:立即执行,完全执行完之后才结束,不会方式回调队列中
列子:数组遍历forEach相关的回调函数
const arr = [1, 3, 5]arr.forEach(item => { // 遍历回调,同步回调函数console.log(item)})console.log('forEach()之后')

异步回调函数
理解:不会立即执行,放入任务队列,等待同步任务执行栈之后完成后调用任务队列中的回调函数才执行
列子:定时器回调、AJAX回调、promise的回调
Promise 是什么
表达:Promise是JS中进行异步变成的新解决方案
具体表达:从语法上,promise是一个构造函数;从功能上,promise对象用来封装一个异步操作并可以获取其结果。
一个Promise的三种状态
在开始使用Promise之前,我们首先需要了解Promise的三种状态:
- pending: 初始状态,既不是成功,也不是失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。
因为Promise.prototype.then和Promise.prototype.catch方法返回promise 对象, 所以它们可以被链式调用。
Promise的这三种状态有两个特点:
- 对象的状态不受外界影响。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 - 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise 基本用法
const p = new Promise((resolve, reject) => { // executor 执行器函数// 执行异步操作代码if(...) {resolve(value); // 成功} else {reject(error); // 失败}
Promise构造函数接收一个函数作为参数,该函数的两个参数分别是resolve和reject。他们是两个函数,由JavaScript引擎提供,不用自己部署。executor 执行器函数是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数。resolve函数的作用:当promise对象的状态从pending变为resovled,在异步操作成功时调用,将异步操作结果作为参数传递出去。reject函数的作用:当promise对象的状态从pending变为rejected,在异步操作失败时调用,将异步操作错误信息作为参数传递出去。promise实例对象生成后,可以用then方法分别执行resolved状态和rejected状态的回调函数。then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
p.then((value) => { // onResolved// success}, (error) => { // onRejected// failure});
promise新建后会立即执行构造器函数部分
let promise = new Promise((resolve, reject) => {console.log('11'); // 会立即执行,同步回调函数,宏任务resolve();});promise.then(() => {console.log('22'); // 微任务});console.log('33');// => 11// => 33// => 22
注意:调用resolve或reject并不会终结 Promise的参数函数的执行。
new Promise((resolve, reject) => {resolve(1); // 不影响console.log(2);}).then(r => {console.log(r);});// 2// 1
promise.then返回的新promise的结果状态有什么决定?
- 由
then指定的回调函数执行的结果决定 - 如果抛出异常,新
promise变为rejected,reason为抛出的异常 - 如果返回的是非
promise的任意值,新promise变为resolved,value为返回的值 - 如果返回的是另一个新
promise对象,此promise的结果就会成为下一个then函数中新promise的结果new Promise((resolve, reject) => {resolve(1); // 不影响console.log(2);}).then(value => {console.log('1', value);return '111';return Promise.resolve(3)}).then(value => {console.log('2',value);// '111' // 获取到上一个then函数里面resolv回调函数中的 return 字符串 '111'// 3 // 获取到上一个then函数里面resolv回调函数中的 return 的promise对象,成功值为3})
promise 如何串联多个操作任务?
promise的then()方法返回一个信息的promise,可以使用then()的链式调用通过
then的链式调用可以串联多个同步或者异步任务(异步任务需要返回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
promise异常穿透
当使用
promise的then链式调用时,可以在最后指定失败的回调- 前面任何操作出了异常,都会传到最后失败的回调中处理
中断promise链
- 当使用
promise的then链式调用时,在中间中断,不再调用后面的回调函数 - 方法:在回调函数中返回一个
pending状态的promise对象new Promise((resolve, reject) => {setTimeout(()=>{console.log('执行任务1(异步)')resolve(1)}, 1000)}).then(value =>{console.log('任务1的结果 =>', value)console.log('执行任务2(同步)')return 2}).catch(reason => {console.log('任务2的结果 =>', reason)return new Promise(() => {})// 返回一个状态为 pending的promise对象,中断 promise 链// 后面的 then 方法也不会执行}).then(value =>{console.log('任务3的结果 =>', value)})
