- 掘金已经有很多的Promise实现代码了,本人结合了下大佬们的代码基本完善了。
人不狠话不多直接上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>promise的实现</title>
</head>
<body>
</body>
</html>
<script>
//定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
const resolvePromise = (bridgePromise, x, resolve, reject) => {
if (x === bridgePromise) {// 循环引用情况
throw new TypeError('Chaining cycle detected for promise #<Promise>');
}
let called = false; // 表示是否调用成功or失败
// 判断x是否是一个promise的办法:
// 1.判断是否是对象或者function
// 2.判断是否有then,并且then是一个方法
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {// 考虑一种很极端的情况,即then属性的getter方法内抛出异常,就是一取x.then就报错
// 是否是thenable对象(具有then方法的对象/函数)
let then = x.then
if (typeof then === 'function') {//此时是一个promise
then.call(x, y => {
// 防止多次调用
if (called) return false
called = true
// y可能还是个promise,所以递归继续解析直到返回一个普通值
resolvePromise(bridgePromise, y, resolve, reject);
}, e => {
if (called) return false
called = true
reject(e)
})
} else {// 说明是一个普通对象/函数,直接返回
resolve(x)
}
} catch (error) {
if (called) return false
called = true
reject(error)
}
} else {
resolve(x)
}
}
const gen = (len, resolve) => {
let values = [], count = 0;
return (value, i) => {
values[i] = value
if (++count === len) {
resolve(values)
}
}
}
class PromiseA {
constructor(executor) {
if (typeof this !== 'object') {// Promise 必须是new 创建出来的
throw new TypeError('PromiseA must be constructed via new')
}
if (typeof executor !== 'function') { // Promise 的参数必须是function
throw new TypeError('PromiseA constructor\'s arguments is not a function')
}
this.status = PENDING // 默认的状态,pending->fulfilled, pending->rejected
this.value = undefined // 成功的值
this.error = undefined // 失败的原因
this.onFulfilledCallbacks = [] // 存放then成功的回调
this.onRejectedCallbacks = [] // 存放then失败的回调
try {
executor(this.resolve.bind(this), this.reject.bind(this)) //new 的时候执行传递resolve和reject函数
} catch (error) {
this.reject(error)
}
// 同步执行resolve,reject,then
// PENDING 时候 then onFulfilled和onRejected列表 中 push 回调函数onFulfilled,onRejected
// resolve setTimeout执行晚于 then 此时 再改变 status状态 并且循环执行onFulfilled和onRejected列表
}
static resolve(value) {
// PromiseA.all
return new PromiseA((resolve, reject) => {
resolve(value)
})
}
static resolve(error) {
// PromiseA.resolve
return new PromiseA((resolve, reject) => {
reject(error)
})
}
static all(promiseList) {
// PromiseA.all
return new PromiseA((resolve, reject) => {
let done = gen(promises.length, resolve);
//利用闭包多次执行后,等promises都完成后resolve
promiseList.forEach((promise, i) => {
promise.then((value) => {
done(value, i)
}, e => {
reject(e)
})
})
})
}
static race(promiseList) {
// PromiseA.race
return new PromiseA((resolve, reject) => {
promiseList.forEach((promise) => {
promise.then(resolve, reject)
})
})
}
static deferred() {//为了通过测试
let def = {};
def.promise = new PromiseA(function (resolve, reject) {
def.resolve = resolve;
def.reject = reject;
});
return def;
}
resolve(value) {
setTimeout(() => {//防止没有异步操作
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.onFulfilledCallbacks.forEach((cb) => cb(this.value))
}
});
}
reject(error) {
setTimeout(() => {
if (this.status === PENDING) {
this.status = REJECTED
this.error = error
this.onRejectedCallbacks.forEach((cb) => cb(this.error))
}
});
}
then(onFulfilled, onRejected) {
//在then中什么都不传的情况,还能继续继续链式调用则判断onFulfilled和onRejected
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
let bridgePromise = new PromiseA((resolve, reject) => {
if (this.status === FULFILLED) {
// 当成功或失败执行时,有异常那么返回的promise应该处于失败态
// 用try/catch来防止返回异常的情况
// 加上setTimeout实现异步调用
setTimeout(() => {
try {
// x可能是个普通值,也可能是个promise
let x = onFulfilled(this.value);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.error);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (err) {
reject(err);
}
})
}
// 当promise的执行器中有异步代码的时候,并且触发状态改变的resolve或者reject
// 在异步代码块中。这种情况下,由于先执行了then,而promise的状态还是PENDING状态
// 所以then方法内的函数便无法执行。
// 此时可先将then方法内的函数参数存储起来,利用订阅-发布模式,当执行器中等的异步代码
// 执行后,触发存储起来的函数的执行。
if (this.status === PENDING) {
console.log('1---- then ' + this.status);
// 当调用then时 可能没成功也没失败,就处于pending状态
this.onFulfilledCallbacks.push(() => {
// 将成功的回调添加到数组中
setTimeout(() => {
console.log('2---- then ' + this.status);
try {
let x = onFulfilled(this.value);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.error);
resolvePromise(bridgePromise, x, resolve, reject);
} catch (err) {
reject(err);
}
})
})
}
})
return bridgePromise;
}
// 捕获错误的方法
catch(onRejected) {
// 也是调用then方法,给成功的回调传一个null,给失败的回调传入callback
return this.then(null, onRejected)
}
}
let p1 = new PromiseA((resolve, reject) => {
// console.log('1');
resolve(1)
})
p1.then((data) => {
console.log(data);
})
</script>