本文手写了一个简易Promise,分别使用了es5、es6两种方式进行模拟。看完本文预计需要3-5分钟。看懂本文你需要明确以下知识点:
- 构造函数及原型链
- class类继承
- this指向
this指向:看调用方式
1. 直接调用函数 window
在 ES5 严格模式 this 指向 undefined
2. 隐式调用(对象调用方式) 调用的对象
a.b.c.d() 指向c
3. 显示调用(call/apply) 指向传入的第一个参数
4. new调用 指向产生的实例对象
5. 回调函数
定时器回调函数 window
在 ES5 严格模式 this 指向 undefined
DOM事件回调函数 绑定事件的DOM元素
React生命周期函数 组件实例对象
React普通函数 默认是undefined
6. 箭头函数
没有自己的this、arguments
看离他最近包裹它函数的this
方式一(es5):
- es没有模块暴露的方法,通常使用立即函数自调用的方式挂载到window上(即IIFE)。
(function (w) {
function MyPromise(executor) {
// promise对象就是this --> new关键字
const that = this;
// 以'_'开头的属性作为私有属性,外界不允许操作
// 初始化promise对象状态是pending状态
that._status = "pending";
//初始化返回的结果容器(resolve或reject中返回的值会存到_result中)
that._result = undefined;
// 用来存储成功、失败回调函数的容器(其实存放的就是then或catch方法中的回调函数)
that._callbacks = {};
function resolve(value) {
// 先进行判断,promise对象状态只能修改一次
if (that._status !== "pending") return;
// 将promise对象状态改成成功状态resolved
that._status = "resolved";
// 把resolve的结果值存放到_result中
this._result = value;
// 触发/调用 onResolved 函数
setTimeout(function () {
// 异步调用 setTimeout
// 新的运算符 ?. 可选链表示存在就调用等同于 that._callbacks.onResolved && that._callbacks.onResolved(value);
that._callbacks.onResolved?.(value);
//需要注意,此处的this.callbacks.onResolved其实就是then或catch方法中的回调(把then方法联系在一起思考)
}, 0);
}
// 将promise对象状态改成失败状态rejected
function reject(reason) {
// 让promise对象状态只能修改一次
if (that._status !== "pending") return;
that._status = "rejected";
// 存错错误原因
this._result = reason;
// 触发/调用 onRejected 函数
setTimeout(function () {
// 同上(resolve)
that._callbacks.onRejected?.(reason);
}, 0);
}
// 同步调用
// executor为new Pormise(()=>{})时传入的回调函数
executor(resolve, reject);
}
MyPromise.prototype.then = function (onResolved, onRejected) {
// this指向实例对象promise
// 将成功、失败回调添加容器中(注意:没有调用)
const that = this;
return new MyPromise(function (resolve, reject) {
// onResolved为then方法中接收结果的回调,存入callbacks中,在上述resolve或reject中调用(关键点)
that._callbacks.onResolved = function (value) {
try {
const result = onResolved(value);
if (result instanceof MyPromise) {
// 说明result是promise对象
result.then(resolve, reject);
// 等同于
// result.then(
// (value) => resolve(value),
// (reason) => reject(reason)
// );
} else {
// 说明没有返回值或者返回值不是promise
resolve(result);
}
} catch (e) {
reject(e);
}
};
this._callbacks.onRejected = function (reason) {
try {
const result = onRejected(reason);
if (result instanceof MyPromise) {
// 说明result是promise对象
result.then(resolve, reject);
// 等同于
// result.then(
// (value) => resolve(value),
// (reason) => reject(reason)
// );
} else {
// 说明没有返回值或者返回值不是promise
resolve(result);
}
} catch (e) {
reject(e);
}
};
});
};
w.MyPromise = MyPromise;
})(window);
方式二(es6):
- 基本过程与es5类似(参考es5写法),使用es6可以使写法更加简单
class MyPromise {
constructor(executor){
this._status = "pending";
this._result = undefined;
// 用来存储成功、失败回调函数的容器
this._callbacks = {};
// executor 是一个执行器,进入会立即执行。 并传入resolve和reject方法
executor(this.resolve, this.reject) }
}
resolve(value) {
// 让promise对象状态只能修改一次
if (this._status !== "pending") return;
// 将promise对象状态改成成功状态resolved
this._status = "resolved";
this._result = value;
// 触发/调用 onResolved 函数
setTimeout(function () {
// 异步调用 setTimeout
// this._callbacks.onResolved && this._callbacks.onResolved(value);
// 新的运算符 ?. 可选链
this._callbacks.onResolved?.(value);
}, 0);
}
reject(reason) {
// 让promise对象状态只能修改一次
if (this._status !== "pending") return;
this._status = "rejected";
this._result = reason;
// 触发/调用 onRejected 函数
setTimeout(function () {
this._callbacks.onRejected?.(reason);
}, 0);
}
then(onResolved, onRejected) {
// 将成功、失败回调添加容器中(注意:没有调用)
return new MyPromise(function (resolve, reject) {
this._callbacks.onResolved = function (value) {
try {
const result = onResolved(value);
if (result instanceof MyPromise) {
// 说明result是promise对象
result.then(resolve, reject);
// result.then(
// (value) => resolve(value),
// (reason) => reject(reason)
// );
} else {
// 说明没有返回值或者返回值不是promise
resolve(result);
}
} catch (e) {
reject(e);
}
};
this._callbacks.onRejected = function (reason) {
try {
const result = onRejected(reason);
if (result instanceof MyPromise) {
// 说明result是promise对象
result.then(resolve, reject);
// result.then(
// (value) => resolve(value),
// (reason) => reject(reason)
// );
} else {
// 说明没有返回值或者返回值不是promise
resolve(result);
}
} catch (e) {
reject(e);
}
};
});
};
}
// exports default = MyPromise
module.exports = MyPromise
本文模拟了一个简易版promise,跟着思路很容易就能理解,文章如果有什么问题欢迎在评论区指出共勉(撰文不易,点赞鼓励,感谢!)