根据Promise/A+规范实现Promise
Promise/A+规范实现Promise,promises-aplus-tests
测试通过。
const PENDING = "PENDING"
const FULFILLED = "FULFILLED"
const REJECTED = "REJECTED"
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError(`Chaining cycle detected for promise #<Promise>`));
}
if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
let then, called;
try {
then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true
resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return;
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if (called) return;
called = true
reject(e)
}
} else {
resolve(x)
}
}
const isPromise = (value) => {
if ((typeof value === 'object' && value !== null) || typeof value === 'function') {
return typeof value.then === 'function'
}
return false
}
class Promise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledCallBack = []
this.onRejectedCallBack = []
const resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.onFulfilledCallBack.forEach(fn => fn())
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.onRejectedCallBack.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => { return value; }
onRejected = typeof onRejected === 'function' ? onRejected : (err) => { throw err; }
let promise2 = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
if (this.status === PENDING) {
this.onFulfilledCallBack.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
this.onRejectedCallBack.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
catch(errCallBack) {
return this.then(null, errCallBack)
}
finally(callback) {
return this.then(value => {
return Promise.resolve(callback()).then(() => value)
}, err => {
return Promise.resolve(callback()).then(() => { throw err; })
})
}
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value)
})
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all(promises) {
return new Promise((resolve, reject) => {
let arr = [], i = 0;
let processData = (index, data) => {
arr[i] = data
if (++i === promises.length) {
resolve(arr)
}
}
if (promises instanceof Array) {
promises.forEach((p, index) => {
if (isPromise(p)) {
p.then((data) => {
processData(index, data)
}, reject)
} else {
processData(index, p)
}
})
} else {
reject()
}
})
}
static race(promises) {
return new Promise((resolve, reject) => {
if (promises instanceof Array) {
for (let i = 0; i < promises.length; i++) {
let current = promises[i]
if (isPromise(current)) {
if (current.value || (!isPromise(current.value) && current.status !== PENDING)) {
resolve(current.value)
}
current.then(resolve, reject)
} else {
resolve(current)
}
}
} else {
reject()
}
})
}
static try(callback) {
return new Promise((resolve, reject) => {
return Promise.resolve(callback()).then(resolve)
})
}
}
Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject
})
return dfd;
}
module.exports = Promise
/**
* 根据Promise/A+规范
* 实现Promise步骤解析:
* 1.Promise的构造函数接收一个函数
* executor(resolve, reject)
* 接收2个参数
* resolve 成功后执行函数,改变value和status
* reject 失败后执行函数,改变reason和status
* 注意:
* 1.一旦创建它就会立即执行,中途无法取消
* 2.一旦状态改变就不会在变
* 3.如果resolve接收的是一个promise,就让它执行then方法并且采用它的状态
* 4.如果抛出异常,需要处理异常情况
* 2.Promise实例生成后,用then方法指定fulfilled 和 rejected状态的回调
* 1).同步函数
* 直接判断status的状态,分别调用onFulfilled或onRjected
* 2).异步函数
* 需要用到订阅发布模式
* 定义两个数组分别保存fulfilled 和 rejected的回调函数,
* 再异步执行到resolve或reject的时候,
* 改变状态获取value或reason,
* 再去执行数组中保存的回调函数
* 3.promise的链式调用
* 特点:
* 1).then中返回一个新的promise对象
* promise2 = new Promise(executor);
return promise2;
* 2).链式调用中,下一个then的状态采用它上一个then的返回
* 需要保存第一个then返回的值,
* a.如果第一个then返回的是普通值(除function,object),会走下一个then的成功
* b.如果第一个then抛出错误,会走下一个then的失败
* c.如果第一个then返回的是一个promise,就让它执行并且采用它的状态
* 此过程需要递归,直到再没有promise为止
* 注意:
* 1.onFulfilled 和 onRejected 不能在当前上下文执行
* 解决办法:使用setTimeout
* 使用setTimeout的还有一个目的:保证能拿到promise2
* 2.then中2个回调都不存在时的处理
* 解决办法:不存在时,需要自己提供默认的函数
* 4.catch的实现
* catch的原理:成功回调函数为null时的then方法
* then(null,onRejected)
* 5.all
* 原理:
* 1).返回一个新的Promise实例(所有的都成功才成功,有一个失败就失败)
* 2).接收一个数组,数组中都是Promise实例,
* 如果不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。
* 3).只有数组中所有的promise的状态都变成fulfilled,状态才会变成fulfilled,返回值组成一个数组,传递给外层的回调函数。
4).只要数组中有一个是rejected,状态就变成rejected,此时第一个被reject的实例的返回值,会传递给外层的回调函数。
* 6.finally
原理:
1).无论如何都执行
如果回调函数中返回promise,等待promise执行完毕,再走下一个then/catch(捕获finally上一个then的成功和失败)
* 7.race
* 原理:
* 1).返回一个新的Promise实例
* 2).接收一个数组,数组中都是Promise实例,
* 如果不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。
* 3).promise数组中谁快返回谁的结果 *
* 8.Promise.resolve和Promise.reject的实现
* Promise.resolve原理:返回一个成功的Promise
* Promise.reject原理:返回一个失败的Promise
* 9.Promise.try
* 原理:
* 1).不管是同步还是异步错误都能捕获
*/