Appearance
手写代码
手写 Promise
1. 初始结构
js
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING;
this.result = null;
// 注意此处this指向, 需要绑定实例
func(this.resolve.bind(this), this.reject.bind(this));
}
resolve(result) {
this.status = MyPromise.FULFILLED;
this.result = result;
}
reject(result) {
this.status = MyPromise.REJECTED;
this.result = result;
}
}
// 调用
const p = new MyPromise((resolve, reject) => {
resolve("success");
});
2. .then
then 接收两个执行函数, 分别状态成功和状态失败所执行的操作
js
class MyPromise {
// ...
then(onFULFILLED, onREJECTED) {
if (this.status === MyPromise.FULFILLED) {
onFULFILLED(this.result);
}
if (this.status === MyPromise.REJECTED) {
onREJECTED(this.result);
}
}
}
const p = new MyPromise((resolve, reject) => {
resolve("success");
});
p.then(
(result) => {
console.log(result);
},
(err) => {
console.log(err);
}
);
3. 处理异常
当抛出错误时, 要能捕获且输出
js
class MyPromise {
// ...
constructor(func) {
this.status = MyPromise.PENDING;
this.result = null;
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
// ...
}
// 调用
const p = new MyPromise((resolve, reject) => {
throw new Error("抛出错误");
});
p.then(
(result) => {
console.log(result);
},
(err) => {
console.log(err);
}
);
- then 的传入参数不为函数时要忽略
js
class MyPromise {
//...
then(onFULFILLED, onREJECTED) {
onFULFILLED = typeof onFULFILLED === "function" ? onFULFILLED : () => {};
onREJECTED = typeof onREJECTED === "function" ? onREJECTED : () => {};
if (this.status === MyPromise.FULFILLED) {
onFULFILLED(this.result);
}
if (this.status === MyPromise.REJECTED) {
onREJECTED(this.result);
}
}
//...
}
// 调用
const p = new MyPromise((resolve, reject) => {
resolve("success");
});
p.then(undefined, (err) => {
console.log(err);
});
4. 实现异步
在 then 内部给执行函数包上定时调用, 初步实现异步
js
class MyPromise {
//...
then(onFULFILLED, onREJECTED) {
onFULFILLED = typeof onFULFILLED === "function" ? onFULFILLED : () => {};
onREJECTED = typeof onREJECTED === "function" ? onREJECTED : () => {};
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result);
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
onREJECTED(this.result);
});
}
}
//...
}
// 调用结果: 1 2 3 success
console.log(1);
const p = new MyPromise((resolve, reject) => {
console.log(2);
resolve("success");
});
p.then((result) => {
console.log(result);
});
console.log(3);
5. 回调保存
当调用时使用 setTimeout
, 需要将 then
中的事件回调保存起来, 等执行到 resolve
或 reject
时处理
js
class MyPromise {
//...
constructor(func) {
this.status = MyPromise.PENDING;
this.result = null;
this.resolveCallbacks = [];
this.rejectCallbacks = [];
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(result) {
setTimeout(() => {
this.status = MyPromise.FULFILLED;
this.result = result;
this.resolveCallbacks.forEach((callback) => {
callback(result);
});
});
}
reject(result) {
setTimeout(() => {
this.status = MyPromise.REJECTED;
this.result = result;
this.rejectCallbacks.forEach((callback) => {
callback(result);
});
});
}
then(onFULFILLED, onREJECTED) {
onFULFILLED = typeof onFULFILLED === "function" ? onFULFILLED : () => {};
onREJECTED = typeof onREJECTED === "function" ? onREJECTED : () => {};
if (this.status === MyPromise.PENDING) {
this.resolveCallbacks.push(onFULFILLED);
this.rejectCallbacks.push(onREJECTED);
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result);
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
onREJECTED(this.result);
});
}
}
}
调用结果==>1 2 4 3 success
js
console.log(1);
const p = new MyPromise((resolve, reject) => {
console.log(2);
setTimeout(() => {
resolve("success");
console.log(3);
});
});
p.then((result) => {
console.log(result);
});
console.log(4);
6. 链式调用
实现 .then
链式调用, 以下是完整代码
js
class MyPromise {
static PENDING = "等待";
static FULFILLED = "成功";
static REJECTED = "失败";
constructor(func) {
this.status = MyPromise.PENDING;
this.result = null;
this.resolveCallbacks = [];
this.rejectCallbacks = [];
try {
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(result) {
setTimeout(() => {
this.status = MyPromise.FULFILLED;
this.result = result;
this.resolveCallbacks.forEach((callback) => {
callback(result);
});
});
}
reject(result) {
setTimeout(() => {
this.status = MyPromise.REJECTED;
this.result = result;
this.rejectCallbacks.forEach((callback) => {
callback(result);
});
});
}
then(onFULFILLED, onREJECTED) {
onFULFILLED = typeof onFULFILLED === "function" ? onFULFILLED : () => {};
onREJECTED = typeof onREJECTED === "function" ? onREJECTED : () => {};
if (this.status === MyPromise.PENDING) {
this.resolveCallbacks.push(onFULFILLED);
this.rejectCallbacks.push(onREJECTED);
}
if (this.status === MyPromise.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result);
});
}
if (this.status === MyPromise.REJECTED) {
setTimeout(() => {
onREJECTED(this.result);
});
}
return this;
}
}
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve("success");
});
});
p.then((result) => {
console.log(result);
}).then(() => {
console.log("链式调用");
});
深拷贝
js
function deepClone(obj = {}) {
if (typeof obj !== "object" || obj === null) {
return obj;
}
let result = obj instanceof Array ? [] : {};
for (const k in obj) {
// 排除原型上的属性,如: Object.prototype.abc = '123' 中的abc
if (Object.hasOwnProperty.call(obj, k)) {
result[k] = deepClone(obj[k]);
}
}
return result;
}