回想起来也是有点小激动,之前面试字节前端实习的时候,一面一上来两道代码题后就是手写Promise了,当时一听到这道题,还真的有点震惊。之前确实有听说过大厂喜欢考手撕代码,没想到一上来就这么爽。
然后呢,我也是最后写出来了这道题,这道题在以前我是有写过的,但是真的到面试的时候脑子确实是有点空白的,当时是第一次在面试的时候遇到这道题,然后我还特地的问了一下面试官,你确定吗?

面试官:嗯嗯
好吧,那我就手撕了一下,但是之前的代码没有保存,我今天就来展现一下我手写的Promise代码
我记得当时大概用时在15 - 20分钟,当时是面试官叫的,然后调试了一下,好像大概调试了5-6分钟。
这个代码是今天写的,并且没有紧张的面试,所以代码质量要高过我面试时写的。
function isFunction(func) {
return typeof func === "function";
}
class MyPromise {
static _PENDING = "pending";
static _FULLFILLED = "fullfilled";
static _REJECTED = "rejected";
_handlers = [];
constructor(resolver) {
this._promiseState = MyPromise._PENDING; // Promise的状态
this._settledValue = null; // Promise已决阶段的数据
try {
resolver(this._resolve.bind(this), this._reject.bind(this)); // this指向很关键
// this.__resolve中用到了this,而在我们传入的函数参数中,这个方法的调用是走预编译过程,this指向全局对象
} catch (error) {
// 函数参数执行过程中抛出错误,立刻触发Promise状态为rejected
this._changeState(MyPromise._REJECTED, error);
}
}
_changeState(state, data) {
if (this._promiseState !== MyPromise._PENDING) {
// 状态发生改变之后不可更改
return;
}
this._promiseState = state;
this._settledValue = data;
this._runHandlers(); // 改变状态后触发
// 触发任务队列的执行有两个时间点
// 1. 状态发生改变之后立刻触发
// 2. then添加任务之后立刻触发,防止有些任务不是在状态改变之前添加的
}
_resolve(data) {
this._changeState(MyPromise._FULLFILLED, data);
}
_reject(reason) {
this._changeState(MyPromise._REJECTED, reason);
}
_removeHandleObj(handles, i) {
handles.splice(i, 1);
}
_runOneHandle({ handle, resolve, reject }) {
setTimeout(() => {
// 宏队列模拟微队列
try {
const result = handle(this._settledValue);
resolve(result);
} catch (error) {
reject(error);
}
});
}
_runHandlers() {
if (this._promiseState === MyPromise._PENDING) {
return;
}
for (let i = 0; i < this._handlers.length; i++) {
const handleObj = this._handlers[i];
if (handleObj.state === this._promiseState) {
this._runOneHandle(handleObj);
}
this._removeHandleObj(this._handlers, i);
i--;
}
}
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
isFunction(onResolved) &&
this._handlers.push({
handle: onResolved,
state: MyPromise._FULLFILLED,
resolve,
reject,
});
isFunction(onRejected) &&
this._handlers.push({
handle: onRejected,
state: MyPromise._REJECTED,
resolve,
reject,
});
this._runHandlers();
});
}
}
调试代码
new MyPromise((resolve, reject) => {
// throw new Error("我是枫枫枫逸");
setTimeout(() => {
resolve(1);
}, 1000);
})
.then(
(data) => {
console.log("data", data);
return 2;
},
(reason) => {
console.log("reason", reason);
}
)
.then((data) => {
console.log("data", data);
});
这大概就是我面试时写到的点,但是还是有缺陷的。
有一点面试时间太紧了,没有考虑到
在执行Promise任务时,没有考虑到如果函数返回的是一个符合Promise A+规范的对象该如何处理
但是估计面试官没打算追问太深,就放过我了
这是考虑到这一点之后我修改的代码
function isFunction(func) {
return typeof func === "function";
}
function isPromise(obj) {
return !!(obj && typeof obj === "object" && typeof obj.then === "function");
}
class MyPromise {
static _PENDING = "pending";
static _FULLFILLED = "fullfilled";
static _REJECTED = "rejected";
_handlers = [];
constructor(resolver) {
this._promiseState = MyPromise._PENDING; // Promise的状态
this._settledValue = null; // Promise已决阶段的数据
try {
resolver(this._resolve.bind(this), this._reject.bind(this)); // this指向很关键
// this.__resolve中用到了this,而在我们传入的函数参数中,这个方法的调用是走预编译过程,this指向全局对象
} catch (error) {
// 函数参数执行过程中抛出错误,立刻触发Promise状态为rejected
this._changeState(MyPromise._REJECTED, error);
}
}
_changeState(state, data) {
if (this._promiseState !== MyPromise._PENDING) {
// 状态发生改变之后不可更改
return;
}
this._promiseState = state;
this._settledValue = data;
this._runHandlers(); // 改变状态后触发
// 触发任务队列的执行有两个时间点
// 1. 状态发生改变之后立刻触发
// 2. then添加任务之后立刻触发,防止有些任务不是在状态改变之前添加的
}
_resolve(data) {
this._changeState(MyPromise._FULLFILLED, data);
}
_reject(reason) {
this._changeState(MyPromise._REJECTED, reason);
}
_removeHandleObj(handles, i) {
handles.splice(i, 1);
}
_runOneHandle({ handle, resolve, reject }) {
setTimeout(() => {
// 宏队列模拟微队列
try {
const result = handle(this._settledValue);
if (isPromise(result)) {
// 如果返回的是一个Promise
// 那么返回的Promise的状态应该与该Promise的状态保持一致
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
}
});
}
_runHandlers() {
if (this._promiseState === MyPromise._PENDING) {
return;
}
for (let i = 0; i < this._handlers.length; i++) {
const handleObj = this._handlers[i];
if (handleObj.state === this._promiseState) {
this._runOneHandle(handleObj);
}
this._removeHandleObj(this._handlers, i);
i--;
}
}
then(onResolved, onRejected) {
return new MyPromise((resolve, reject) => {
isFunction(onResolved) &&
this._handlers.push({
handle: onResolved,
state: MyPromise._FULLFILLED,
resolve,
reject,
});
isFunction(onRejected) &&
this._handlers.push({
handle: onRejected,
state: MyPromise._REJECTED,
resolve,
reject,
});
this._runHandlers();
});
}
}
手写Promise之后我觉得对Promise的了解也更加深刻。
当然我写的肯定跟大佬们的不能比,只希望能提供一个思考的方向,觉得有帮助的别忘了点赞哦~~
