基本Promise类
- 属性:state,value和reason
- 转变状态:resolve和reject
- promise中有隐式try…catch调用
- then方法
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECT = 'REJECT'
class MyPromise {
constructor(executor) {
this.state = undefined
this.value = undefined
this.reason = undefined
const resolve = val => {
if (this.state === PENDING) {
this.state = FULFILLED
this.value = val
}
}
const reject = reason => {
if (this.state === PENDING) {
this.state = REJECT
this.reason = reason
}
}
try {
executor()
} catch(err) {
reject(err)
}
}
then(onResolve, onReject) {
if (this.state === FULFILLED) {
onResolve(this.val)
}
if (this.state === REJECT) {
onReject(this.reason)
}
}
}
扩展then方法
then的异步调用
调用then方法时,若状态还在PENDING,则先将onResolve和onReject放进回调队列,FULFILLED/REJECT后执行并清空相应队列。
class MyPromise {
constructor(executor) {
...
this.onFulfilledCallbacks = []
this.onRejectCallbacks = []
const resolve = val => {
if (this.state === PENDING) {
···
this.onRejectCallbacks.forEach(cb => cb())
}
}
const reject = reason => {
if (this.state === PENDING) {
···
this.onRejectCallbacks.forEach(cb => cb())
}
}
try {
executor()
} catch(err) {
reject(err)
}
}
then(onResolve, onReject) {
···
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => onResolve(this.value))
this.onRejectCallbacks.push(() => onReject(this.value))
}
}
}
then的链式调用
then方法需返回新的Promise对象,方可继续链式调用。将then中的逻辑包装成新的Promise对象并返回,其中若是发生错误,直接reject
then(onFulfilled, onRejected) {
const promiseInst = new MyPromise((resolve, reject) => {
if (this.state === FULFILLED) {
try {
onFulfilled(this.value);
} catch (err) {
reject(err);
}
}
if (this.state === REJECT) {
try {
onRejected(this.reason);
} catch (err) {
reject(err);
}
}
if (this.state === PENDING) {
this.onFulfilledCallbacks.push(() => {
try {
onFulfilled(this.value);
} catch (err) {
reject(err);
}
});
this.onRejectedCallbacks.push(() => {
try {
onRejected(this.reason);
} catch (err) {
reject(err);
}
});
}
});
return promiseInst;
}
Promise.all
接收由promise对象组成的数组(可迭代对象即可),当所有promise都resolve时,它才会resolve,结果数组成为它的结果(元素顺序与对象在数组中的顺序相同,不管所花费的时间顺序);
当任意一个promise被reject时,新promise立刻reject,带有error就是被reject的error,其他promise仍会执行,但是它们的状态及结果都会被忽略。
Promise.prototype.all = function(promiseArr) {
if (!isIterable(promiseArr)) {// 判断是否可以迭代
throw new Error()
}
let valueArr = [], len = promiseArr.length, storedArrNum = 0
if (len === 0) return Promise.resolve([])
return new Promise((resolve, reject) => {
if (isPromise(promise)) {
promise.then(value => putInValueArr(value, idx, resolve), reject)
} else {
putInValueArr(promise, idx, resolve)
}
})
function putInValueArr(value, idx, resolve) {
valueArr[idx] = value
if (++storedArrNum === len) {
resolve(valueArr)
}
}
}
function isIterable(obj) {
if (obj !== null && obj !== undefined && typeof obj[Symbol.iterator] === 'function') {
return true
}
return false
}
function isPromise(promise) {
if (promise == null || promise === undefined) return false
if (typeof promise.then === 'function') return true
}
Promise.allSettled
不管接收的数组中promise都状态如何,只要都settled了,就返回一个由{status,value/reason}对象组成的数组。
allSettled(promiseArr) {
if (!isIterable(promiseArr)) {
throw new Error()
}
let valueArr = [], len = promiseArr.length, storedArrNum = 0
if (len === 0) {
return MyPromise.resolve([])
}
return new Promise((resolve) => {
promiseArr.forEach((promise, idx) => {
if (isPromise(promise)) {
promise.then(val => putInValueArr(FULFILLED, val, idx, resolve), reason => putInValueArr(REJECT, reason, idx, resolve))
} else {
putInValueArr(promise, FULFILLED, idx, resolve)
}
})
})
function putInValueArr(status, val, idx, resolve) {
switch (status) {
case FULFILLED: {
valueArr[idx] = {
status,
value: val
}
}
case REJECT: {
valueArr[idx] = {
status,
reason: val
}
}
}
if (++storedArrNum === len) {
resolve(valueArr)
}
}
}
Promise.race
只返回最先settled的promise结果:value/reason
race(promiseArr) {
if (!isIterable(promiseArr)) {
throw new Error()
}
let len = promiseArr.length
if (len === 0) promise.resolve([])
return new Promise((resolve, reject) => {
promiseArr.forEach(promise => {
if (isPromise(promise)) {
promise.then(val => resolve(val), reason => reject(reason))
} else {
resolve(promise)
}
})
})
}
Promise.finally
不管链前promise状态如何,finally做常规工作(清理、扫尾),并将前面的状态通过promise链传递。
finally(finallyCB) {
return this.then(value => new Promise.resolve(finallyCB()).then(() => value),
reason => new Promise.resolve(finallyCB()).then(() => {throw reason}))
}