手写一个promise
Promise是JavaScript中的异步编程解决方案,可以避免回调地狱,使代码更加清晰易读。下面是一个手写的Promise实现:
class Promise {
constructor(executor) {
this.status = 'pending'; // Promise状态,初始为pending
this.value = undefined; // Promise的值,初始为undefined
this.reason = undefined; // Promise的原因,初始为undefined
this.onResolvedCallbacks = []; // Promise resolve时的回调函数列表
this.onRejectedCallbacks = []; // Promise reject时的回调函数列表
// 定义resolve函数,将Promise状态改为resolved并执行回调函数列表
const resolve = (value) => {
if (this.status === 'pending') {
this.value = value;
this.status = 'resolved';
this.onResolvedCallbacks.forEach(fn => fn());
}
}
// 定义reject函数,将Promise状态改为rejected并执行回调函数列表
const reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
this.onRejectedCallbacks.forEach(fn => fn());
}
}
// 执行executor函数,并传入resolve和reject函数
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 定义then方法,返回一个新的Promise实例
then(onResolved, onRejected) {
// 如果onResolved不是函数,则将其替换成返回输入值的函数
onResolved = typeof onResolved === 'function' ? onResolved : value => value;
// 如果onRejected不是函数,则将其替换成抛出输入错误的函数
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error };
// 定义新的Promise实例
const promise2 = new Promise((resolve, reject) => {
if (this.status === 'resolved') {
// 如果当前Promise状态为resolved,则执行onResolved函数,并将返回值作为新的Promise值
setTimeout(() => {
try {
const x = onResolved(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.status === 'rejected') {
// 如果当前Promise状态为rejected,则执行onRejected函数,并将返回值作为新的Promise值
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 如果当前Promise状态为pending,则将回调函数加入回调函数列表
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onResolved(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
// 返回新的Promise实例
return promise2;
}
// 定义catch方法,返回一个新的Promise实例
catch(onRejected) {
return this.then(null, onRejected);
}
// 定义静态resolve方法,返回一个resolved状态的Promise实例
static resolve(value) {
return new Promise(resolve => {
resolve(value);
});
}
// 定义静态reject方法,返回一个rejected状态的Promise实例
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
// 定义静态all方法,返回一个新的Promise实例,当所有Promise实例都为resolved时,返回所有Promise实例的值组成的数组;当有一个Promise实例为rejected时,返回该Promise实例的原因
static all(promises) {
return new Promise((resolve, reject) => {
const values = [];
let count = 0;
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
values[i] = value;
count++;
if (count === promises.length) {
resolve(values);
}
}, reason => {
reject(reason);
});
}
});
}
// 定义静态race方法,返回一个新的Promise实例,当有一个Promise实例状态改变时,返回该Promise实例的值或原因
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
Promise.resolve(promises[i]).then(value => {
resolve(value);
}, reason => {
reject(reason);
});
}
});
}
}
// 定义resolvePromise函数,用于处理then方法返回的值和新的Promise实例的关系
function resolvePromise(promise, x, resolve, reject) {
if (promise === x) {
reject(new TypeError('Chaining cycle detected for promise'));
} else if (x instanceof Promise) {
x.then(
value => {
resolvePromise(promise, value, resolve, reject);
},
reason => {
reject(reason);
}
);
} else if (typeof x === 'object' || typeof x === 'function') {
if (x === null) {
resolve(x);
}
let then = null;
try {
then = x.then;
} catch (error) {
reject(error);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
value => {
if (called) {
return;
}
called = true;
resolvePromise(promise, value, resolve, reject);
},
reason => {
if (called) {
return;
}
called = true;
reject(reason);
}
);
} catch (error) {
if (called) {
return;
}
called = true;
reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
原文地址: https://www.cveoy.top/t/topic/ZUL 著作权归作者所有。请勿转载和采集!