Promise可以实现链式调用,既then之后可以接着使用then方法
let p = new Promise((resolve, reject) => {
resolve('a')
})
p.then((value) => {
return value
}, (reason) => {
return reason
}).then((value) => {
console.log(value) //a
})
分析
- then的方法执行后返回一个Promise对象
- then中onFulfilled或onRejected执行的结果会传入下一个Promise中
- 如果then中onFulfilled或onRejected执行的结果为普通值,则作为下一个promise中的resolve执行
- 如果为Promise,则令其then执行,直到为普通值,讲结果传入下一个Promise中的resolve或reject
- 如果出错,则 reject
设计思路
- 声明一个函数resolvePromise,专门处理上一个then中的onFulfilled或onRejected返回的的结果是否是Promise
- then方法中新建一个Promise对象并返回
- 将上一个onFulfilled或onRejected的执行放在下一个Promise中的executor中执行,这样方便获取其返回值
- 返回的结果可能是新声明的Promise本身,所以也要判断一下
- 同步无法先在executor中获取到声明的Promise对象,所以要改成异步
- resolvePromise也可能出错,在外面加上try…catch
- 出错直接走reject
const PENDING = "PENDING"
const FULFILLED = "FULFILLED"
const REJECTED = "REJECTED"
function resolvePromise (p, x, resolve, reject) {
}
class Promise {
constructor(executor) {
this.state = PENDING
this.value = undefined
this.reason = undefined
this.resolveCallback = []
this.rejectCallback = []
const resolve = (value) => {
//只有当状态是PENDING时才能改变状态
if (this.state === PENDING) {
this.state = FULFILLED
this.value = value
this.resolveCallback.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.state === PENDING) {
this.state = REJECTED
this.reason = reason
this.rejectCallback.forEach(fn => fn())
}
}
//,默认执行构造器
try {
executor(resolve, reject);
} catch (e) {
//如果出错这直接变成错误状态
reject(e)
}
}
then (onFulfilled, onRejected) {
let p = new Promise((resolve, reject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(p, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0);
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(p, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0);
}
if (this.state === PENDING) {
this.resolveCallback.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(p, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0);
})
this.rejectCallback.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(p, x, resolve, reject)
}
catch (e) {
reject(e)
}
}, 0);
})
}
})
return p
}
}
module.exports = Promise
resolvePromise的操作逻辑:
- 判断是否是新创建的Promise对象本身,若是这直接reject
- 判断是否为Promise对象若是,执行then方法
- 执行完then之后若value或reason为普通值,执行resolv或reject
- 若为promise,则继续递归resolvePromise
- 出错直接reject
- 若为常量,直接resolve
function resolvePromise (p, x, resolve, reject) {
//若为其本身
if (x === p) {
//抛出错误
reject(new Error('错误'))
}
if (typeof x === 'object' && x !== null || typeof x === 'function') {
// 如果x是用户定义的Promise,为防止其规范,加上一个防护措施,防止状态二次改变
let called = false
// try一下,x即使有then方法也不一定能调用,defineProperty定义可以设置限制
try {
let then = x.then;
//可以认为是Promise
if (typeof then === 'function') {
// 执行then,采用call执行,不宜直接调用,
then.call(x, (value) => {
if (called) {
return;
}
called = true
//递归
resolvePromise(p, value, resolve, reject)
}, (reason) => {
if (called) {
return
}
called = true
reject(reason)
})
} else {
if (called)
return
called = true
resolve(x)
}
}
catch (e) {
reject(e)
}
}
else {
resolve(x)
}
}