Promise API 详细了解
- Promise在执行这个类的时候,需要传递一个执行器进去,这个执行器会立即执行,执行器这个回调函数,还有两个参数,这里两个参数分别是resolve,reject,调用resolve,reject就是修改promise的状态
- promise 中有三种状态:pending fulfilled,rejected,promise pending => fulfuiiled pending => rejected 一旦状态改变就不可更改
- resolve跟reject用来更改状态
new Promise(function (resolve, reject) {
resolve('成功')
reject('失败')
})
Promise.all
Promise.all是静态方法,接受一个数组,数组中可以是任何数据类型,如果是一个Promise对象,调用.then方法则会等待异步的执行完毕,then中的callback执行时机取决于数组列表中的promise最长消耗的时间
const timeoutAsync = timer => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(timer)
}, timer)
})
}
const p1 = timeoutAsync(1)
const p2 = timeoutAsync(2)
Promise.all([p1, p2]).then(rs => {
console.log(rs)
console.log(rs instanceof Array) // true
}, err => {
// 此处err是第一个发生reject的promise返回结果,参数类型取决于reject的结果
console.log(err)
})
Promise.race
静态方法
const timeoutAsync = timer => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(timer)
}, timer)
})
}
const p1 = timeoutAsync(1)
const p2 = timeoutAsync(2)
Promise.race([p1, p2]).then(rs => {
console.log(rs) // 1
}, err => {
console.log(err)
})
Promise.prototype.then
// then方法接受两个参数,一个是成功的回调,一个失败的回调
const p2 = timeoutAsync(2).then(rs => {
console.log(rs)
}, err => {
})
// 支持多次调用
p2.then()
p2.then()
p2.then(rs => rs1).then(rs1 => rs2)
// 支持链式调用,第二个then方法回调函数的参数是上一个回调函数的返回值
// 如果是普通值,直接返回,如果是promise,则等待异步操作调用结束,返回resolve,reject传递进来的值
实现一个Promise
// promise的三种状态,更改之后不可变
const PENDING = 'pending'
const FULFILLED = 'fullfiled'
const REJECTED = 'rejected'
class MyPromise {
status = PENDING
// then方法的参数回调函数调用返回的值
value = undefined
reason = undefined
successCallback = []
failCallback = []
constructor(executor) {
// 捕获执行器的错误
try {
// 立即执行,传入resolve,reject
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
resolve = value => {
// 状态不是PENDING的时候阻止向下执行
if (this.status !== PENDING) {
return
}
this.value = value
this.status = FULFILLED
while(this.successCallback.length) {
this.successCallback.shift()()
}
}
reject = reason => {
// 状态不是PENDING的时候阻止向下执行
if (this.status !== PENDING) {
return
}
this.reason = reason
this.status = REJECTED
while(this.failCallback.length) {
this.failCallback.shift()()
}
}
// 状态为FULFILLED时候调用成功回调,状态为REJECTED的时候调用failCallback回调
then = (successCallback, failCallback) => {
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => reason
// 返回的promise支持链式调用,内部executor是同步执行,所以可以把then方法的逻辑放入执行器中
const thenPromise = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 使用setTimeout为了拿到thenPromise
setTimeout(() => {
// 捕获成功回调的错误
try {
let r = successCallback(this.value)
// 判断返回值是普通值还是promise对象,
resolvePromise(thenPromise, r, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let r = failCallback(this.reason)
// 判断返回值是普通值还是promise对象,
resolvePromise(thenPromise, r, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
// 如果executor中没有异步状态,那么执行到then方法的时候状态不是PEDING,如果executor里边有异步操作,则需要判断PENDING的情况
// 所以需要讲then方法中传递进来的回调函数保存起来,等到resolve,reject的时候调用对应的回调函数
} else {
this.successCallback.push(() => {
setTimeout(() => {
try {
let r = successCallback(this.value)
// 判断返回值是普通值还是promise对象,
resolvePromise(thenPromise, r, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let r = failCallback(this.reason)
// 判断返回值是普通值还是promise对象,
resolvePromise(thenPromise, r, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
function resolvePromise(thenPromise, r, resolve, reject) {
// 判断如果then方法回调函数返回的promise是本身,返回一个循环引用错误
if (thenPromise === r) {
reject(new TypeError('cycle call'))
return;
}
// 如果是promise对象,则处理then方法的逻辑
if (r instanceof MyPromise) {
r.then(resolve, reject)
} else {
// 如果是普通值,直接resolve
resolve(r)
}
}
// then方法返回一个promise实现链式调用
return thenPromise;
}
static all = array => {
const result = []
return new MyPromise((resolve, reject) => {
let index = 0
function addData (key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}
for (let i=0;i<array.length;i++) {
const current = array[i]
if (current instanceof MyPromise) {
current.then(value => addData(i, value), reason => addData(i, reason))
} else {
addData(i, current)
}
}
})
}
finally = callback => {
return this.then(value => {
return Promise.resolve(callback()).then(() => value)
}, reason => {
return Promise.resolve(callback()).then(() => {throw reason})
})
}
catch = failCallback => {
return this.then(undefined, failCallback)
}
static resolve = value => {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
static reject = value => {
if (value instanceof MyPromise) return value
return new MyPromise(undefined, reject => reject(value))
}
}
module.exports = MyPromise