Promise异步方案、宏任务和微任务队列
2021-01-06 本文已影响0人
翔子丶
一种更优的异步编程统一方案,避免回调地狱。Promise对象能把异步操作最终成功的返回值或失败原因和相应的处理程序关联起来,这样使得异步方法可以和同步方法那样返回值:异步方法不会立即返回最终值,而是返回一个promise,在未来某个时刻把值交给使用者
Promise特点
1.Promise是一个类 执行时传递一个执行器进去 执行器立即执行
2.Promise三种状态 pedding等待 fulfilled成功 rejected失败 只能由pedding->fulfilled或pedding->rejected 一旦状态确定就不能更改
3.参数resolve和reject 更改状态
4.then方法定义在原型对象上 用于判断状态 分别调用对应的回调函数
5.then成功和失败的回调都有返回值
6.同一个Promise对象下的then方法可被多次调用;返回一个全新的Promise对象、后面的then是为上一个then返回的Promise注册回调、前面then回调函数中的返回值作为后面then方法回调的参数
7.then可被链式调用 后面的then拿到的值是上一个then方法的回调函数返回值 不传参数时相当于value => value 状态向后传递
8.finally中代码 不管哪种状态都会执行
9.all方法 参数必须为数组 非promise all自动将其转换为promise对象 传入的值必须按顺序输出 一旦有一个reject则状态立马变为reject 并将错误原因抛出
10.race方法 同all 数组中有一个promise最先得到结果 返回哪种状态 race就返回那种状态
示例:
-
promise封装ajax// Promise 方式的 AJAX function ajax (url) { return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest() xhr.open('GET', url) xhr.responseType = 'json' xhr.load = () => { if (this.status === 200) { resolve(this.response) } else { reject(new Error(this.statusText)) } } }) } ajax('/api/foo.json').then(res => { console.log(res) }, error => { console.log(error) }) -
promise链式调用// 避免回调地狱 ajax('/api/users.json') .then(value => { console.log(1111) return ajax('/api/urls.json') }) // => Promise .then(value => { console.log(2222) console.log(value) return ajax('/api/urls.json') }) // => Promise .then(value => { console.log(3333) return ajax('/api/urls.json') }) // => Promise .then(value => { console.log(4444) return 'foo' }) // => Promise .then(value => { console.log(5555) console.log(value) }) -
异常处理
// then(onRejected) 相当于then(undefined, onRejected) // then(undefined, onRejected)只能捕获当前promise对象的异常 // 如果链式调用某一个节点发生异常 需要一直向后传递 直至被捕获 // then(onRejected)相当于给整个Promise链条注册失败回调 ajax('/api/users.json') .then(value => { console.log('onFulfilled', value) return ajax('/error-url') }, error => { console.log('onRejected', error) }) ajax('/api/users.json') .then(value => { console.log('onFulfilled', value) return ajax('/error-url') }) // => Promise {} .catch(error => { console.log('onRejected', error) }) -
静态方法
Promise.resolve('foo').then(value => console.log(value)) // 如果传入的是一个 Promise 对象,Promise.resolve 方法原样返回 const promise = ajax('/api/user') const promise2 = Promise.resolve(promise) promise === promise2 // true // 如果传入带有then方法的对象,会将这个对象作为promise执行 Promise.resolve({ then: (onFulfilled, onRejected) => { onFulfilled('foo') } }).then(value => { console.log(value) }) // Promise.reject 传入任何值,都会作为这个 Promise 失败的理由 Promise.reject('anything').catch((error) => console.log(error)) // promise.all所有成功触发成功回调 有一个失败就触发失败 ajax('/api/users.json') ajax('/api/posts.json') const promise = Promise.all([ ajax('/api/users.json'), ajax('/api/posts.json') ]) promise.then(value =>{ console.log(value) }).catch(error => { console.log(error) }) // promise.race一旦一个执行成功或失败 会将这个成功或失败的返回值返回 // Promise.race 实现超时控制 const request = ajax('/api/posts.json') const timeout = new Promise((resolve, reject) => { setTimeout(() => reject(new Error('timeout')), 500) }) Promise.race([ request, timeout ]) .then(value => { console.log(value) }) .catch(error => { console.log(error) }) -
宏任务、微任务
// 微任务 console.log('global start') // setTimeout 的回调是 宏任务,进入回调队列排队 setTimeout(() => { console.log('setTimeout') }, 0) // Promise 的回调是 微任务,本轮调用末尾直接执行 Promise.resolve() .then(() => { console.log('promise') }) .then(() => { console.log('promise 2') }) .then(() => { console.log('promise 3') }) console.log('global end')