一、核心实现
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
function Promise (executor) {
const self = this
self.status = PENDING // promise的状态 分别是pending | fulfiled | rejected
self.value = '' // 成功的值
self.reason = '' //失败的原因
self.onFulfiled = [] // 保存成功的回调
self.onRejected = [] // 保存失败的回调
function resolve (value) {
if (self.status !== PENDING) return
self.status = FULFILLED
self.value = value
self.onFulfiled.forEach(fn => fn())
}
function reject(reason) {
if (self.status !== PENDING) return
self.status = REJECTED
self.reason = reason
self.onRejected.forEach(fn => fn())
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
Promise.prototype.then = function (onFulfiled, onRejected) {
onFulfiled = typeof onFulfiled === 'function'? onFulfiled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}
const self = this
const promise2 = new Promise((resolve, reject) => {
// 如果fulfiled | rejected 则直接执行回调
if (self.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfiled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else if(self.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(self.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
} else {
self.onFulfiled.push(() => {
setTimeout(() => {
try {
const x = onFulfiled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
self.onRejected.push(() => {
setTimeout(() => {
try {
const x = onRejected(self.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
function resolvePromise(promise2, x, resolve, reject) {
// 如果返回的值x就是promise2, 就是循环调用了
if(promise2 === x) {
reject(new TypeError('Chaining cycle'))
}
if (x && typeof x === 'object' || typeof x === 'function') {
let called;
try {
const then = x.then
if (typeof then === 'function') { // x是promise类型
then.call(x, y => {
if (called) return
called = true
// 需要递归调用resolvePromise,防止y也循环调用了promise2,或者y也是一个promise对象
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return
called = true
reject(r)
})
} else { // x是普通的对象
if (called) return
called = true
resolve(x)
}
} catch (e) {
if (called) return
called = true
reject(e)
}
} else {
// x是普通类型的值
resolve(x)
}
}
二、其它方法
1. resolve 方法
功能分析
会返回一个由 value 来决定的 Promise 对象,value 有以下几种情况:
- value 本身就是
promise对象,就直接返回该对象 - value 是一个 thenable 对象(即,带有
then方法的对象),返回的promise对象最终状态由 then 方法执行决定 - value 是空、基本类型或者不带
then方法的对象
功能实现
Promise.resolve = function (value) {
// 传入的value,本身就是promise实例,就直接返回
if (value instanceof Promise) return value
return new Promise((resolve, reject) => {
// 带有then方法的对象
if (value && typeof value === 'object' && value.then === 'function' ) {
setTimeout(() => {
value.then(resolve, reject)
})
} else {
// 普通值
resolve(value)
}
})
}
测试一下
// 输出 1 3:1 2
Promise.resolve(new Promise((resolve, reject) => {
console.log(1)
resolve('1')
})).then(res => {
console.log('3',res)
})
console.log('2')
// 输出 1 2
Promise.resolve(2).then(res => {
console.log(res)
})
console.log('1')
//
// 输出 30
const p2 = Promise.resolve({
then: (resolve, reject) => {
resolve(30)
}
})
p2.then(res => {
console.log(res)
})
2. reject 方法
功能分析
返回一个状态失败的 Promise 对象,并将给定的失败信息传递给对应的处理方法
功能实现
Promise.reject = function (reason) {
return new Promise((reolve, reject) => {
reject(reson)
})
}
3. Promise.prototype.catch
功能分析 用于指定出错时的回调,是特殊的 then 方法,catch 之后可以继续.then
功能实现
Promise.prototype.catch = function (onRejected) {
this.then(null, onRejected)
}
**PS:**如果前面 then 方法中有 onRejected 回调,catch 方法是不会执行的
4. Promise.prototype.finally
功能分析 不管成功还是失败,都是执行 finally 中的内容,还可以继续后面的 then,并且将值原封不动的传递给后面的 then。
功能实现
Promise.prototype.finally = function (callBack) {
return this.then(value => {
return Promise.resolve(callBack()).then(() => {
return value
})
}, err => {
return Promise.reject(callBack()).then(() => {
throw err;
})
})
}
PS: 主要是为了避免同样的语句需要在 then、catch 中各写一次的情况
5.Promise.all 方法
该方法接收一个 promise 的 iterable(PS: Array, Map, Set) 类型的输入,并且返回一个 Promise 实例
功能分析
- 如果传入的参数是一个空的可迭代的对象,则返回一个已完成状态的 promise
- 如果传入的参数不包含任何的 promise,则返回一个异步完成
- 如果传入的参数中有一个 promise 失败,则直接返回失败的值
- 如果传入的参数中的 promise 都成功了,则将结果按参数传入的顺序返回
功能实现
Promise.all = function (promises) {
promises = Array.from(promises) // 将迭代对象转换为数组
return new Promise((resolve, reject) => {
let index = 0
let result = []
// promises 为空,返回一个已完成的状态
if (promises.length === 0) {
resolve(result)
} else {
function processValue (i, data) {
result[i] = data
if (++index === promises.length) {
resolve(result)
}
}
for(let i = 0, len = promises.length; i < len; i++) {
// promises[i] 可能是一个普通的
Promise.resolve(promises[i]).then(res => {
processValue(i, res)
}, err => {
reject(err)
})
}
}
})
}
6. Promise.race
方法返回一个 promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。
功能分析
- 如果传入的参数数组是空,则返回的 promise 将永远为等待状态
- 如果迭代包含一个或多个非承诺和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值
功能实现
Promise.race = function (promises) {
promises = Array.from(promise)
return new Promise ((resolve, reject) => {
if (promises.length === 0) return
for (let i = 0, len = promises.length; i < len; i++) {
Promise.resolve(promises[i]).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}