JS 手写 Promise
2020-09-25 本文已影响0人
limengzhe
基本定义
-
Promise
对象用于表示一个异步操作的最终完成或失败的状态, 并返回相应的结果值; -
Promise
是一个类,在执行这个类的时候,需要传递一个执行器,执行器会立即执行; -
Promise
有三个状态:等待pending
、成功fulfilled
和失败rejected
。
语法
const promise = new Promise((resolve, reject) => {
resolve({ a: 1 });
// reject("failed");
});
promise.then(
res => {
console.log(res);
},
err => {
console.log(err);
}
);
核心代码手写实现
// 状态
PENDING = "pending";
FULFILLED = "fulfilled";
REJECTED = "rejected";
//
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject);
}
status = PENDING;
data = undefined;
error = undefined;
resolve = data => {
if (this.status !== PENDING) return;
this.data = data;
this.status = FULFILLED;
};
reject = error => {
if (this.status !== PENDING) return;
this.error = error;
this.status = REJECTED;
};
then(success, fail) {
if (this.status === FULFILLED) {
success(this.data);
} else if (this.status === REJECTED) {
fail(this.error);
}
}
}
module.exports = MyPromise;
测试
const MyPromise = require("./02-my-promise");
const promise = new MyPromise((resolve, reject) => {
resolve({ a: 1 });
// reject("failed");
});
promise.then(
res => {
console.log(res); // expected output: { a: 1 }
},
err => {
console.log(err); // expected output: failed
}
);
完整代码手写实现
// 状态
PENDING = "pending";
FULFILLED = "fulfilled";
REJECTED = "rejected";
//
class MyPromise {
constructor(executor) {
// 捕获错误
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
// Promise 状态
status = PENDING;
// 成功后返回的数据
data = undefined;
// 失败后返回的原因
error = undefined;
// 成功回调
success = [];
// 失败回调
fail = [];
//
resolve = data => {
if (this.status !== PENDING) return;
this.status = FULFILLED;
this.data = data;
// 如果成功回调存在,则依次调用
while (this.success.length) this.success.shift()(this.data);
};
reject = error => {
if (this.status !== PENDING) return;
this.status = REJECTED;
this.error = error;
// 如果失败回调存在,则依次调用
while (this.fail.length) this.fail.shift()(this.error);
};
then(success, fail) {
success = success ? success : value => value;
// 链式调用
let promise = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
// 捕获错误
try {
let value = success(this.data);
// 判断返回值是普通值还是 Promise
resolvePromise(promise, value, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
// 捕获错误
try {
let value = fail(this.error);
// 判断返回值是普通值还是 Promise
resolvePromise(promise, value, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.success.push(() => {
setTimeout(() => {
// 捕获错误
try {
let value = success(this.data);
// 判断返回值是普通值还是 Promise
resolvePromise(promise, value, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.fail.push(() => {
setTimeout(() => {
// 捕获错误
try {
let value = fail(this.error);
// 判断返回值是普通值还是 Promise
resolvePromise(promise, value, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise;
}
// catch
catch(fail) {
return this.then(null, fail);
}
// finally
finally(callback) {
return this.then(
data => {
return MyPromise.resolve(callback().then(() => data));
},
err => {
return MyPromise.resolve(
callback().then(() => {
throw err;
})
);
}
);
}
// all 方法
static all(array) {
let result = [];
let index = 0;
//
return new MyPromise((resolve, reject) => {
//
function addData(key, value) {
index++;
result[key] = value;
index === array.length && resolve(result);
}
//
for (let i = 0; i < array.length; i++) {
const current = array[i];
if (current instanceof MyPromise) {
current.then(
data => addData(i, data),
err => reject(err)
);
} else {
addData(i, current);
}
}
});
}
// resolve 方法
static resolve(value) {
if (value instanceof MyPromise) return value;
return new MyPromise(resolve => resolve(value));
}
}
function resolvePromise(promise, value, resolve, reject) {
if (promise === value) {
return reject(
new TypeError("Chaining cycle detected for promise #<Promise>")
);
}
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}
module.exports = MyPromise;