大体思路:
resolve方法实现异步的回调并得到结果通知,然后再通知onFulfilled
reject方法实现异步的回调并得到错误反馈,然后再通知onRejected
then方法实现对onFulfilled和onRejected的二次封装后,加载到回调队列_resolveQueue/_rejectQueue,等候通知,并且返回新的pomise实现链式调用
版本一
这个版本有个问题:当传给reject回调的参数是 promise 对象时,没做处理。
// Promise/A+ 规范规定的三种状态
const STATUS = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected'
}
class MyPromise {
// 构造函数接收一个执行回调
constructor(executor) {
this._status = STATUS.PENDING // Promise初始状态
this._value = undefined // then回调的值
this._resolveQueue = [] // resolve时触发的成功队列
this._rejectQueue = [] // reject时触发的失败队列
// 使用箭头函数固定this(resolve函数在executor中触发,不然找不到this)
const resolve = value => {
const run = () => {
// Promise/A+ 规范规定的Promise状态只能从pending触发,变成fulfilled
if (this._status === STATUS.PENDING) {
this._status = STATUS.FULFILLED // 更改状态
this._value = value // 储存当前值,用于then回调
// 执行resolve回调
while (this._resolveQueue.length) {
const callback = this._resolveQueue.shift()
callback(value)
}
}
}
//把resolve执行回调的操作封装成一个函数,放进setTimeout里,以实现promise异步调用的特性(规范上是微任务,这里是宏任务)
setTimeout(run)
}
// 同 resolve
const reject = value => {
const run = () => {
if (this._status === STATUS.PENDING) {
this._status = STATUS.REJECTED
this._value = value
while (this._rejectQueue.length) {
const callback = this._rejectQueue.shift()
callback(value)
}
}
}
setTimeout(run)
}
// new Promise()时立即执行executor,并传入resolve和reject
executor(resolve, reject)
}
// then方法,接收一个成功的回调和一个失败的回调
then(onFulfilled, onRejected) {
// 根据规范,如果then的参数不是function,则忽略它, 让值继续往下传递,链式调用继续往下执行
typeof onFulfilled !== 'function' ? onFulfilled = value => value : null
typeof onRejected !== 'function' ? onRejected = error => error : null
// then 返回一个新的promise
return new MyPromise((resolve, reject) => {
const resolveFn = value => {
try {
const x = onFulfilled(value)
// 分类讨论返回值,如果是Promise,那么等待Promise状态变更,否则直接resolve
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
}
const rejectFn = error => {
try {
const x = onRejected(error)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
}
switch (this._status) {
case STATUS.PENDING:
this._resolveQueue.push(resolveFn)
this._rejectQueue.push(rejectFn)
break;
case STATUS.FULFILLED:
resolveFn(this._value)
break;
case STATUS.REJECTED:
rejectFn(this._value)
break;
}
})
}
catch(rejectFn) {
return this.then(undefined, rejectFn)
}
finally(callback) {
return this.then(value => MyPromise.resolve(callback()).then(() => value), error => {
MyPromise.resolve(callback()).then(() => error)
})
}
// 静态resolve方法
static resolve(value) {
return value instanceof MyPromise ? value : new MyPromise(resolve => resolve(value))
}
// 静态reject方法
static reject(error) {
return new MyPromise((resolve, reject) => reject(error))
}
// 静态all方法
static all(promiseArr) {
let count = 0
let result = []
return new MyPromise((resolve, reject) => {
if (!promiseArr.length) {
return resolve(result)
}
promiseArr.forEach((p, i) => {
MyPromise.resolve(p).then(value => {
count++
result[i] = value
if (count === promiseArr.length) {
resolve(result)
}
}, error => {
reject(error)
})
})
})
}
// 静态race方法
static race(promiseArr) {
return new MyPromise((resolve, reject) => {
promiseArr.forEach(p => {
MyPromise.resolve(p).then(value => {
resolve(value)
}, error => {
reject(error)
})
})
})
}
}
版本二
// 判断变量否为function
const isFunction = variable => typeof variable === 'function'
// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'
class MyPromise {
constructor (handle) {
if (!isFunction(handle)) {
throw new Error('MyPromise must accept a function as a parameter')
}
// 添加状态
this._status = PENDING
// 添加状态
this._value = undefined
// 添加成功回调函数队列
this._fulfilledQueues = []
// 添加失败回调函数队列
this._rejectedQueues = []
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this))
} catch (err) {
this._reject(err)
}
}
// 添加resovle时执行的函数
_resolve (val) {
const run = () => {
if (this._status !== PENDING) return
// 依次执行成功队列中的函数,并清空队列
const runFulfilled = (value) => {
let cb;
while (cb = this._fulfilledQueues.shift()) {
cb(value)
}
}
// 依次执行失败队列中的函数,并清空队列
const runRejected = (error) => {
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(error)
}
}
/* 如果resolve的参数为Promise对象,则必须等待该Promise对象状态改变后,
当前Promsie的状态才会改变,且状态取决于参数Promsie对象的状态
*/
if (val instanceof MyPromise) {
val.then(value => {
this._value = value
this._status = FULFILLED
runFulfilled(value)
}, err => {
this._value = err
this._status = REJECTED
runRejected(err)
})
} else {
this._value = val
this._status = FULFILLED
runFulfilled(val)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
// 添加reject时执行的函数
_reject (err) {
if (this._status !== PENDING) return
// 依次执行失败队列中的函数,并清空队列
const run = () => {
this._status = REJECTED
this._value = err
let cb;
while (cb = this._rejectedQueues.shift()) {
cb(err)
}
}
// 为了支持同步的Promise,这里采用异步调用
setTimeout(run, 0)
}
// 添加then方法
then (onFulfilled, onRejected) {
const { _value, _status } = this
// 返回一个新的Promise对象
return new MyPromise((onFulfilledNext, onRejectedNext) => {
// 封装一个成功时执行的函数
let fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
onFulfilledNext(value)
} else {
let res = onFulfilled(value);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
// 封装一个失败时执行的函数
let rejected = error => {
try {
if (!isFunction(onRejected)) {
onRejectedNext(error)
} else {
let res = onRejected(error);
if (res instanceof MyPromise) {
// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调
res.then(onFulfilledNext, onRejectedNext)
} else {
//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数
onFulfilledNext(res)
}
}
} catch (err) {
// 如果函数执行出错,新的Promise对象的状态为失败
onRejectedNext(err)
}
}
switch (_status) {
// 当状态为pending时,将then方法回调函数加入执行队列等待执行
case PENDING:
this._fulfilledQueues.push(fulfilled)
this._rejectedQueues.push(rejected)
break
// 当状态已经改变时,立即执行对应的回调函数
case FULFILLED:
fulfilled(_value)
break
case REJECTED:
rejected(_value)
break
}
})
}
// 添加catch方法
catch (onRejected) {
return this.then(undefined, onRejected)
}
// 添加静态resolve方法
static resolve (value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
// 添加静态reject方法
static reject (value) {
return new MyPromise((resolve ,reject) => reject(value))
}
// 添加静态all方法
static all (list) {
return new MyPromise((resolve, reject) => {
/**
* 返回值的集合
*/
let values = []
let count = 0
for (let [i, p] of list.entries()) {
// 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
this.resolve(p).then(res => {
values[i] = res
count++
// 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
if (count === list.length) resolve(values)
}, err => {
// 有一个被rejected时返回的MyPromise状态就变成rejected
reject(err)
})
}
})
}
// 添加静态race方法
static race (list) {
return new MyPromise((resolve, reject) => {
for (let p of list) {
// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
this.resolve(p).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
finally (cb) {
return this.then(
value => MyPromise.resolve(cb()).then(() => value),
reason => MyPromise.resolve(cb()).then(() => { throw reason })
);
}
}
版本三
const isFunc = obj => Object.prototype.toString.call(obj) === '[object Function]';
const isObj = obj => Object.prototype.toString.call(obj) === '[object Object]';
// 等待态 规范 2.1.1
const PENDING = 'pending';
// 执行态 规范 2.1.2
const FULFILLED = 'fulfilled';
// 拒绝态 规范 2.1.3
const REJECTED = 'rejected';
class MyPromise {
constructor(fn) {
this.status = PENDING;
this.value = undefined;
this.filfulledQueues = [];
this.rejectedQueues = [];
try {
fn(this._resolve.bind(this), this._reject.bind(this));
} catch (err) {
this._reject(err);
}
}
//传入 promise 的第一个参数 resolve
_resolve(val) {
if (val instanceof MyPromise) {
val.then(this._resolve, this._reject);
} else if (isObj(val) || isFunc(val)) {
try {
if (isFunc(val.then)) {
val.then(this._resolve, this._reject);
}
} catch (e) {
this._reject(e);
}
}
this._execCallback(FULFILLED, this.filfulledQueues, val);
}
//传入 promise 的第二个参数 reject
_reject(val) {
this._execCallback(REJECTED, this.rejectedQueues, val);
}
_execCallback(status, list, val) {
//规范 2.2.4 onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用,且被作为函数调用(即没有 this 值)
setTimeout(() => {
if (this.status !== PENDING) {
return;
}
this.status = status;
this.value = val;
let cb;
//规范 2.2.6
while ((cb = list.shift())) {
cb(val);
}
});
}
//规范 2.3 Promise 解决过程 [[Resolve]](promise, x)
_resolvePromise(newPromise, x, resolve, reject) {
if (newPromise === x) {
//规范 2.3.1
return reject(new TypeError('循环引用'));
}
if (x instanceof MyPromise) {
//规范 2.3.2
x.then(resolve, reject);
} else if (isObj(x) || isFunc(x)) {
//规范 2.3.3
try {
//规范 2.3.3.3
if (isFunc(x.then)) {
x.then(resolve, reject);
} else {
//规范 2.3.3.4
resolve(x);
}
} catch (e) {
//规范 2.3.3.3.4
reject(e);
}
} else {
//规范 2.3.4
resolve(x);
}
}
//规范 2.2
then(onFulfilled, onRejected) {
let newPromise;
//规范 2.2.1,2.2.7.3
onFulfilled = isFunc(onFulfilled) ? onFulfilled : val => val;
//规范 2.2.1,2.2.7.4
onRejected = isFunc(onRejected)
? onRejected
: err => {
throw err;
};
//规范 2.2.7 then 方法必须返回一个 promise 对象:promise2 = promise1.then(onFulfilled, onRejected);
return (newPromise = new MyPromise((onFulfilledNext, onRejectedNext) => {
// onFulfilledNext, onRejectedNext 即该 then 的下一个 then 里传的 resolve 和 reject
if (this.status === FULFILLED || this.status === REJECTED) {
//规范 2.2.4 onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用
setTimeout(() => {
// 规范 2.2.7.1 不论 promise1 被 reject 还是被 resolve 时 promise2 都会被 resolve(走_resolvePromise方法),只有出现异常时才会被 rejected。
try {
//规范 2.2.2,2.2.3,2.2.5
const x = this.status === FULFILLED ? onFulfilled(this.value) : onRejected(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2 这里如果x为捕获的err(即 onRejected 不是函数 2.2.7.4)也会进入
onRejectedNext(e);
}
});
} else if (this.status === PENDING) {
//规范 2.2.6.1
this.filfulledQueues.push(() => {
try {
//规范 2.2.2,2.2.5
const x = onFulfilled(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2
onRejectedNext(e);
}
});
//规范 2.2.6.2
this.rejectedQueues.push(() => {
try {
//规范 2.2.3,2.2.5
const x = onRejected(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2
onRejectedNext(e);
}
});
}
}));
}
//catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
//finally 方法
finally(cb) {
return this.then(
val => {
MyPromise.resolve(cb()).then(() => val);
},
err => {
MyPromise.resolve(cb()).then(() => {
throw err;
});
}
);
}
//resolve 方法
static resolve(params) {
return new MyPromise(resolve => {
resolve(params);
});
}
//reject 方法
static reject(err) {
return new MyPromise((resolve, reject) => {
reject(err);
});
}
//all 方法
static all(params) {
let count = 0;
let valueList = [];
const promises = Array.from(params);
return new MyPromise((resolve, reject) => {
promises.forEach((item, index) => {
if (!item instanceof MyPromise) {
item = MyPromise.resolve(item);
}
item.then(r => {
valueList[index] = r;
if (promises.length === ++count) {
resolve(valueList);
}
}, reject);
});
});
}
//race 方法
static race(params) {
const promises = Array.from(params);
return new MyPromise((resolve, reject) => {
promises.forEach(item => {
if (!item instanceof MyPromise) {
item = MyPromise.resolve(item);
}
item.then(resolve, reject);
});
});
}
}
参考
Promise系列2——Promises_A+ 规范解读
https://promisesaplus.com/
看了就会,手写Promise原理,最通俗易懂的版本!!!
promise规范实现
Promise知识汇总和面试情况