Promise概述
promise对象表示一个异步任务最终结束时的状态,成功fulfilled或者失败rejected,在状态明确之后会有对应的任务被自动执行。并且状态一旦确定就不再更改。
promise基本用法
new Promise((resolve, reject) => {
// 调用resolve 更改状态为fulfilled,并将异步的结果通过resolve函数的参数传递出去
resolve()
// 调用reject 更改状态为rejected,并将为什么失败的理由通过reject函数的参数传递出去
reject()
})
因为Promise对象的状态一旦确认就不能更改,所以resolve与reject只能调用其一
当两个都没有被调用(一直处于碰pending状态),那么then方法里面的回调都不会执行
Promise链式调用
- Promise的then方法会返回一个全新Promise对象
- 后面的then方法就是为上一个then方法返回的全新Promise对象注册回调
- 前面then方法回调函数的返回值会作为后面then方法回调的参数(没有返回值,then接收的是undefined)
- 如果回调的返回值是Promise对象,那后面then方法的回调会等待它的结束(如果返回其他任何值,则会立即执行下一级.then())
Promise异常处理
// 第一种作为then方法的第二个参数
new Promise((resolve, reject) => {
reject('失败')
})
.then(val => console.log(val), e => console.log)
// 第二种作为Promise对象的方法
new Promise((resolve, reject) => {
reject('失败')
})
.then(val => console.log(val))
.catch(e => console.log(e))
推荐使用第二种方式,更加清晰好读,并且可以捕获前面所有的错误(可以捕获N个then回调错误),第一种只能捕获当前promise对象的异常
// catch方法就是then方法的别名 下面写法是一样的
// catch也会同then里面失败回调一样存在返回值,返回一个promise实例或普通值,都能被下个then 的成功回调接收(resolved状态),如果抛出错误则变为rejected状态
.then(val => console.log(val), e => console.log(e))
.catch(undefined, e => console.log(e))
promise执行时序
then方法是作为微任务加入到本轮事件循环后面的,then方法里面若存在微任务,那么该微任务并不是加入到下次事件循环中去,而是依旧加入本次事件循环
手写Promise
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = 'pedding'
value = undefined
reason = undefined
successCallback = []
failCallback = []
resolve = value => {
if(this.status !== 'pedding') return
this.status = 'fulfilled'
this.value = value
while(this.successCallback.length) this.successCallback.shift()(this.value)
}
reject = reason => {
if(this.status !== 'pedding') return
this.status = 'rejected'
this.reason = reason
while(this.failCallback.length) this.failCallback.shift()(this.reason)
}
// then方法也是立即执行的,当Promise构造函数中存在异步的时候(status===pending)
// successCallback或failCallBack不能立即执行,这时候保存下来,等异步执行完成,去执行resolve或reject函数时调用callback
then(successCallback, failCallback) {
let p = new MyPromise((resolve, reject) => {
if(this.status === 'fulfilled') {
let x = successCallback(this.value)
// resolve(x)
resolvePromise(x, resolve, reject)
} else if(this.status === 'rejected') {
failCallback(this.reason)
} else if(this.status === 'pedding') {
this.successCallback.push(successCallback)
this.failCallback.push(failCallback)
}
})
return p
}
static all (array) {
let resule = []
let index = 0
let promise = new MyPromise((resolve, reject) => {
function addDate (key, value) {
resule[key] = value
index++
index === array.length && resolve(resule)
}
for(let i = 0; i < array.length; i++) {
let item = array[i]
if(item instanceof MyPromise) {
item.then((val) => addDate(i, val))
} else {
addDate(i, item)
}
}
})
return promise
}
}
function resolvePromise (value, resolve, reject) {
if(value instanceof MyPromise) {
value.then(resolve, reject)
} else {
resolve(value)
}
}
let p1 = new MyPromise((resolve, reject) => {
resolve('11111')
})
let p2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('777777')
}, 2000)
})
MyPromise.all([p1, p2, 3])
.then(val => console.log(val, '-----'))