/**
* promise是一个类,在执行这个类时,需传递一个执行器进去,执行器回立即执行
* Promise有三个状态,分别为 等待pending、成功fulfilled、失败rejected
* pending -> fulfilled -> rejected
* resolve和reject函数用来更改状态的,分别为:resolve->fulfilled , reject->rejected
* then方法内部做的事情是判断状态,如果成功则调用成功的回调函数,失败调用失败的回调函数
* then成功回调有一个参数,表示成功后的值;失败回调有一个参数,表示失败的原因
* then方法是定义在原型对象之中
*/
// 创建初始状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECT = 'reject'
// 链式结构
function resolvePromise(promise2, x, resolve, reject) {
// 判断:防止陷入循环引用
if (x === promise2) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
let called = false; // 多次调用节流阀
// x为有内容并且类型为object或function
if (x != null && (typeof x === 'object' && typeof x === 'function')) {
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, y => {
// 成功和失败只能调用一个
if (called) return
called = true
// 继续解析
resolvePromise(promise2, y, resolve, reject)
}, err => {
// 成功和失败只能调用一个
if (called) return
called = true
// 报错
reject(err)
})
} else {
resolve(x)
}
} catch (e) {
// 同样为失败,跳出错误信息
if (called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
class MyPromise {
// 构造器
constructor(executor) {
// 异常则执行reject
try {
executor(this.resolve, this.reject)
} catch(err) {
this.reject(err)
}
}
// 初始状态
status = PENDING
// 声明 成功的初始值(value)/失败的原因(reason)
value = undefined
reason = undefined
// 声明 成功/失败的回调函数
successCallback = undefined
failCallback = undefined
resolve = (value) => {
// 判断状态,如不为等待pending则退出,否则就继续执行;状态修改为成功
if (this.status != PENDING) return
this.status = FULFILLED
// 传入初始值
this.value = value
}
reject = (reason) => {
// 判断状态,如不为等待pending则退出,否则就继续执行;状态修改为失败
if (this.status != PENDING) return
this.status = REJECT
// 传入报错原因
this.reason = reason
}
// then方法中传入成功和失败的回调函数
then (successCallback, failCallback) {
if (this.status === FULFILLED) {
successCallback(this.value)
} else if (this.status === REJECT) {
failCallback(this.reason)
}
}
}
module.exports = MyPromise
// 调用
const MyPromise = require('./MyPromise')
let promise = new MyPromise((resolve, reject) => {
resolve('ok')
reject('error')
})
promise.then(value => {
console.log(value) // ok
}, reason => {
console.log(reason) // error
})