实现:
/* 概念 */
// MyPromise 是具有then方法的对象或函数,行为符合Promise/A+规范。
// thenable 是定义then方法得对象或函数
// value 是任何合法的Javascript值(包括undefined,ableable或promise)
// 异常 exception throw 语句抛出的值
// reason 是表明拒绝promise的原因
/* MyPromise 的状态 */
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
/* 规范中的resolvePromise(promise2, x) 规定 */
// 1、如果promise和x指向相同的对象,会导致循环调用,直接返回失败
// 2、如果x是一个promise:查看x的状态 pending 则需等待状态改变,fulfilled value 为 promise的值 ,reject reason为promise的reason
// 3、如果x是一个对象或一个函数: 执行x的then方法
// 3.1、如果 没有x.then 则直接返回失败
// 3.2、如果 有x.then 且为函数,则执行 then.call(),参数:x 作为this,成功时的回调,失败时的回调。
// 3.2.1、如果成功的回调还是promise,值为y,再次调用 resolvePromise(promise2, y, resolve, reject)
// 3.2.2、如果失败,则执行失败回到,原因为r,直接返回失败
// 3.2.3、成功和失败只能调用一个,所以设定一个isCalled来防止多次调用
// 3.3、如果 有x.then但不是函数,则将x作为promise的值
// 4、如果x不是对象也不是函数:把x作为promise的值,设置成fulfilled状态
const resolvePromise = (promise2, x, resolve, reject) => {
// A+规范中 x和promise2引用同一个对象抛出类型错误
if (promise2 === x) {
return reject(
new TypeError("Chaining cycle detected for MyPromise #<MyPromise>")
);
}
// 只可以调用一个
let isUsed;
// 后续的条件要严格判断 保证代码能和别的库一起使用
// x可能是一个函数或者对象
if (x instanceof MyPromise) {
// 判断 x 为 MyPromise
x.then(
(value) => {
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
reject(reason);
}
);
} else if (x !== null && (typeof x === "object" || typeof x === "function")) {
// x 为对象或函数
try {
let then = x.then;
if (typeof then === "function") {
// 只能判断then是函数就认为其是promise
then.call(
x,
(y) => {
if (isUsed) return;
isUsed = true;
resolvePromise(promise2, y, resolve, reject);
},
(e) => {
if (isUsed) return;
isUsed = true;
reject(e);
}
);
} else {
if (isUsed) return;
isUsed = true;
resolve(x);
}
} catch (e) {
if (isUsed) return;
isUsed = true;
reject(e);
}
} else {
//返回的基本类型,直接resolve
resolve(x);
}
};
// 定义一个 class
class MyPromise {
// ========>A+规范:传入一个参数(函数),该函数为立即执行函数,这里面我们起名为 executor
constructor(executor) {
if (typeof executor !== "function") {
throw new TypeError(`MyPromise resolver ${executor} is not a function`);
}
// 初始状态
this.state = PENDING;
// 成功返回值
this.value = undefined;
// 失败返回值
this.reason = undefined;
// 成功存放方法的数组
this.onResolvedCallbacks = [];
// 失败存放方法的数组
this.onRejectedCallbacks = [];
// resolve函数,将状态更改为FULFILLED
let resolve = (value) => {
this.state = FULFILLED;
this.value = value;
// 一旦 resolve 执行, 则按顺序 调用 成功数组 中的函数
this.onResolvedCallbacks.forEach((fn) => fn());
};
// inject函数,将状态更改为REJECTED
let inject = (reason) => {
this.state = REJECTED;
this.reason = reason;
// 一旦 reject 执行, 则按顺序 调用 失败数组 中的函数
this.onRejectedCallbacks.forEach((fn) => fn());
};
// 如果 executor 报错 立即执行 reject
try {
// 立即执行函数
// ========>A+规范:executor 函数接收两个参数,resolve 与 reject,成功时resolve(value),失败时reject(reason)。
executor(resolve, inject);
} catch (error) {
inject(error);
}
}
/* ========>A+规范: 一个 MyPromise 必须提供 then 方法,访问其当前或最终value或reason */
// then 方法必须返回一个Promise
// 如果 onFulfilled 或 onRejected 执行时报错,则直接返回失败
// onFulfilled 不是函数,promise1的状态是fulfilled :这时 promise2的状态是fulfilled,值同promise1
// onRejected 不是函数,promise1 的状态是 rejected:这时promise2的状态是 rejected,拒绝原因 reason 同promise1
// 如果一个 onFulfilled 或 onRejected 返回一个值 x(自己return x),则需要对x进行处理,处理的函数叫做:resolvePromise(promise2, x)
// 1: MyPromise 成功或者失败会传递到外层的下一个then方法
// 2: 返回的是普通值(除了promise之外的值)都会触底到下一then的成功中;出错的情况走到下一次的失败中;
// 3: 错误处理 。自己最近的then没有错误处理,会向下传递错误直到有错误处理
// 4: 每次执行完then 返回都是新的promise (一旦成功或者失败就不能够修改状态)
then(onFulfilled, onRejected) {
// // onFulfilled 为可选参数 如果不为函数 则忽略onFulfilled 直接返回 value
// typeof onFulfilled === "function" ? onFulfilled : (value) => value;
// // onRejected 为可选参数 如果不为函数 则忽略onFulfilled 直接抛出错误
// typeof onRejected === "function"
// ? onRejected
// : (error) => {
// throw error;
// };
// 链式调用
let promise2 = new MyPromise((resolve, inject) => {
if (this.state === FULFILLED) {
setTimeout(() => {
try {
// 如果状态是成功了,需要调用传入的第一个onFulfilled函数
//成功的回调直接执行;执行完成后拿到结果;ps: 成功之后返回的直接执行拿到结果存放到x中
// 但是返回的promise 还能继续then,继续传递成功的结果
let x = onFulfilled(this.value);
// x可能是promise,解析promise ,使用这个返回的结果决定下一个then是成功还是失败
resolvePromise(promise2, x, resolve, inject); // 调用了下一个promise的resolve
} catch (error) {
inject(error);
}
}, 0);
}
if (this.state === REJECTED) {
setTimeout(() => {
try {
// 如果状态失败了,就需要使用第二个函数讲失败的原因返回
let x = onRejected(this.reason);
// 处理失败
resolvePromise(promise2, x, resolve, inject); //普通值都会传递到下一个的成功
} catch (error) {
inject(error);
}
}, 0);
}
if (this.state === PENDING) {
this.onResolvedCallbacks.push(() => {
// todo
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, inject);
} catch (error) {
inject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
// todo
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, inject);
} catch (error) {
inject(error);
}
}, 0);
});
}
});
// 返回promise,完成链式
return promise2;
}
// catch 方法
catch(errCallBack) {
return this.then(null, errCallBack);
}
static resolve(data) {
// 快速创建一个成功的promise
return new MyPromise((resolve, reject) => {
resolve(data);
});
}
static reject(reason) {
// 快速创建一个失败的promise
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
static all(promiseArr) {
let result = [];
let i = 0;
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseArr.length; i++) {
if (isPromise(promiseArr[i])) {
promiseArr[i].then((data) => {
result[i] = data;
if (result.length === promiseArr.length) {
resolve(result);
}
}, reject);
} else {
result[i] = promiseArr[i];
}
}
});
}
static race(promiseArr) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseArr.length; i++) {
promiseArr[i].then(resolve, reject);
}
});
}
static finally(fn) {
return new MyPromise((resolve, reject) => {
try {
fn();
} catch (error) {
reject(error);
}
if (this.state === "fulfilled") {
resolve(this.value);
}
if (this.state === "rejected") {
reject(this.reason);
}
});
}
}
function isPromise(obj) {
return (
!!obj &&
(typeof obj === "object" || typeof obj === "function") &&
typeof obj.then === "function"
);
}
module.exports = MyPromise;
测试:
const MyPromise = require("./Promise.js");
let p = new MyPromise((resolve, inject) => {
console.log("1111111");
resolve("数据1");
});
p.then(
(res) => {
console.log("第一次then res");
console.log(res);
return res;
},
(error) => {
console.log("第一次then error");
console.log(error);
}
)
.then(
(res) => {
console.log("第二次then res");
console.log(res);
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(res);
// reject(res);
}, 100);
});
},
(error) => {
console.log("第二次then error");
console.log(error);
}
)
.then(
(res) => {
console.log("第三次then res");
console.log(res);
return res;
},
(err) => {
console.log("第三次then error");
console.log(err);
return "error";
}
)
.catch((data) => {
console.log(data);
});
结果:
1111111
第一次then res
数据1
第二次then res
数据1
第三次then res
数据1