const { reject } = require("lodash");
//模拟promise\
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
//promise是个类,传入一个执行器并立即执行
constructor(fn) {
try {
fn(this.resolve, this.reject);
} catch (error) {
//当抛出错误时,then的reject能捕捉到
this.reject(error);
}
}
//不同实例,状态、resolve/reject、value/reason都不同,所以属性用表达式写在实例上
status = PENDING;
value = undefined;
reason = undefined;
fulfilledCallback = []; //数组能 同时存储多个回调函数
rejectedCallback = [];
resolve = (value) => {
//箭头函数保证this指向实例
if (this.status !== PENDING) return; //状态一旦确定就不能改变
this.status = FULFILLED;
this.value = value;
while (this.fulfilledCallback.length) {
this.fulfilledCallback.shift()();
}
};
reject = (reason) => {
if (this.status !== PENDING) return; //状态一旦确定就不能改变
this.status = REJECTED;
this.reason = reason;
while (this.rejectedCallback.length) {
this.rejectedCallback.shift()();
}
};
//then是原型上的
then(onFulfilled, onRejected) {
//如果没有传参,需要补上
onFulfilled = onFulfilled ? onFulfilled : (value) => value;
onRejected = onRejected
? onRejected
: (reason) => {
// 用throw的原因:then的方法里面,调用reject的地方写在了catch里;
throw reason;
};
//函数作参数]
//若异步时多个then被调用:要将回调函数用数组存储起来
//then链式调用:返回promise对象,且return出去的值作为新promise的resolve的值
let newPromise = new MyPromise((resolve, reject) => {
//立即执行函数
if (this.status === FULFILLED) {
setTimeout(() => {
try {
//捕获then回调里抛出的错误
const res = onFulfilled(this.value); //把return出来的值传给了resolve,then的回调就拿到了
//1.要判断是否是循环调用res === newPromis就是循环调用
//2、res是普通值(直接调用resolve) or promise对象(判断promise返回值是成功(调用resolve)还是失败(调用 reject))
handleRes(newPromise, res, resolve, reject);
} catch (error) {
reject(error);
}
}, 0); //目的:异步才可以拿到newPromise
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
//捕获then回调里抛出的错误
const res = onRejected(this.reason); //把return出来的值传给了resolve,then的回调就拿到了
//1.要判断是否是循环调用res === newPromis就是循环调用
//2、res是普通值(直接调用resolve) or promise对象(判断promise返回值是成功(调用resolve)还是失败(调用 reject))
handleRes(newPromise, res, resolve, reject);
} catch (error) {
reject(error);
}
}, 0); //目的:异步才可以拿到newPromise
}
// 异步情况,status仍是pending,那就先将将传入的参数存起来,等待status的改变,
if (this.status === PENDING) {
this.fulfilledCallback.push(() => {
setTimeout(() => {
try {
//捕获then回调里抛出的错误
const res = onFulfilled(this.value); //把return出来的值传给了resolve,then的回调就拿到了
//1.要判断是否是循环调用res === newPromis就是循环调用
//2、res是普通值(直接调用resolve) or promise对象(判断promise返回值是成功(调用resolve)还是失败(调用 reject))
handleRes(newPromise, res, resolve, reject);
} catch (error) {
reject(error);
}
}, 0); //目的:异步才可以拿到newPromise
});
this.rejectedCallback.push(() => {
setTimeout(() => {
try {
//捕获then回调里抛出的错误
const res = onRejected(this.reason); //把return出来的值传给了resolve,then的回调就拿到了
//1.要判断是否是循环调用res === newPromis就是循环调用
//2、res是普通值(直接调用resolve) or promise对象(判断promise返回值是成功(调用resolve)还是失败(调用 reject))
handleRes(newPromise, res, resolve, reject);
} catch (error) {
reject(error);
}
}, 0); //目的:异步才可以拿到newPromise
});
}
});
return newPromise;
}
//catch返回promise
catch(callback) {
return this.then(undefined, callback);
}
//finally无论失败还是成功都会走一次,返回一个promise可以在.then里拿到结果
//如果finally的回调函数有返回值(普通值(转成promise对象)/promise对象(等待执行完成返回value))用到rsolve,
finally(callback) {
//无论失败还是成功都会走
return this.then(
//finally返回promise,所以可以直接返回this.then
(value) => {
return MyPromise.resolve(callback()).then(() => value); //后面的then需要拿到值
},
(reason) => {
return MyPromise.resolve(callback()).then(() => {
throw reason;
}); //后面的then需要拿到值
}
);
}
//Promise.all([]),all方法是用类调用的,所以是一个静态方法;返回值是一个promise
//数组里面如果是普通值,就放到结果数组中;如果是promise对象,就先去执行promise对象,将执行结果放到结果数组中
static all(arr) {
let resArr = []; //结果数组
let length = 0; //因为可能有的promise的立即执行函数是异步的,需要等待
return MyPromise((resolve, reject) => {
function addResArr(index, res) {
//需要保证顺序
resArr[index] = res;
length++;
if (length === arr.length) {
resolve(resArr);
}
}
for (let index = 0; index < arr.length; index++) {
//判断每一项是否是普通值
if (arr[index] instanceof MyPromise) {
arr[index].then(
(res) => {
addResArr(index, res);
},
(reason) => {
reject(reason);
}
);
} else {
addResArr(index, arr[index]);
}
}
});
}
//Promise.resolve(10);resolve方法接收的参数如果是普通值,会返回一个promise,并且结果为普通值;如果为promise对象,会将这个传入的普通对象返回;
static resolve(data) {
// 判断传入值是普通值还是promise
if (data instanceof MyPromise) {
return data;
} else {
return new MyPromise((resolve, reject) => resolve(data));
}
}
}
const handleRes = function (newPromise, res, resolve, rejct) {
if (newPromise === res) {
return reject("TypeError: Chaining cycle detected for promise #<Promise>");
}
if (res instanceof MyPromise) {
//res是promise对象
//res.then((value)=>{resolve(value),(reason)=>{reject(reason)}});
res.then(resolve, rejct);
} else {
resolve(res);
}
};
//测试
const resPromise = new MyPromise((resolve, reject) => {
resolve("干你丫的小日本儿");
});
const promise = new MyPromise((resolve, reject) => {
// setTimeout(() => {
// resolve("成功了");
// }, 5000);
// resolve("成功");
reject("失败");
// throw new Error("promise error"); //throw可以抛出任何类型的值,throw语句的作用是手动中断程序执行,抛出一个错误。
});
// 多次调用
promise.then(
(res) => {
console.log(1, "res", res);
},
(reason) => {
console.log(2, "reason", reason.message);
}
);
promise.then((res) => {
console.log(3, "res", res);
});
// 链式调用
promise
.then(
(res) => {
console.log(11, "res", res);
return "中国必胜";
// return resPromise;
// throw new Error("then error");
},
(error) => {
console.log(22, error);
return 1000;
}
)
.then(
(r) => {
console.log(33, "--r--", r);
},
(reason) => {
console.log(44, "reason", reason.message);
}
);
/**
* 什么是promise的循环调用
* then return出去的promise对象是他自身生成的新的promise对象
*/
// const promise1 = new Promise((resolve, reject) => {
// resolve(100);
// });
// const promise2 = promise1.then((res) => {
// return promise2; //自己返回了自己,导致陷入循环
// });
// promise2.then(
// () => {},
// (reason) => {
// console.log("-----循环-----", reason);
// }
// );
面试 - 实现最全 promise
于 2022-08-05 23:00:23 首次发布