返回
从使用层面手写Promise源码解析及使用规则
前端
2023-11-04 10:45:24
Promise:深入解析其实现与使用
Promise,JavaScript 中的异步利器
在 JavaScript 开发中,我们经常需要处理异步操作。Promise 作为一种优雅高效的机制,正是为应对这一挑战而生。它能够帮助我们轻松管理异步任务,并通过一系列方法和规则确保代码的清晰性和可维护性。
Promise 源码实现
要深入理解 Promise,我们可以从其源码实现入手:
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state !== 'pending') return;
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(value));
};
const reject = (reason) => {
if (this.state !== 'pending') return;
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(reason));
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const value = onFulfilled(this.value);
resolve(value);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const reason = onRejected(this.reason);
resolve(reason);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const value = onFulfilled(this.value);
resolve(value);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const reason = onRejected(this.reason);
resolve(reason);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
return this.then(
(value) => {
onFinally();
return value;
},
(reason) => {
onFinally();
throw reason;
}
);
}
static resolve(value) {
return new Promise((resolve) => resolve(value));
}
static reject(reason) {
return new Promise((resolve, reject) => reject(reason));
}
static all(promises) {
return new Promise((resolve, reject) => {
let results = [];
let completedCount = 0;
promises.forEach((promise, index) => {
promise
.then((value) => {
results[index] = value;
completedCount++;
if (completedCount === promises.length) {
resolve(results);
}
})
.catch((reason) => reject(reason));
});
});
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise) => {
promise
.then((value) => resolve(value))
.catch((reason) => reject(reason));
});
});
}
}
Promise 使用规则
在使用 Promise 时,需要遵循一些基本规则:
- Promise 是一个对象,可通过
new
创建。 - 构造函数接受一个 executor 函数,该函数有两个参数:resolve 和 reject。
- resolve 函数用于将 Promise 状态更改为 "fulfilled",并传递成功值。
- reject 函数用于将 Promise 状态更改为 "rejected",并传递失败原因。
- then 方法用于在 Promise 状态改变时执行回调函数。
- catch 方法用于在 Promise 状态变为 "rejected" 时执行回调函数。
- finally 方法用于无论 Promise 状态如何都执行回调函数。
- Promise.resolve 方法用于创建一个立即成功解析的新 Promise。
- Promise.reject 方法用于创建一个立即失败解析的新 Promise。
- Promise.all 方法用于等待一组 Promise 全部完成,然后以成功状态解析,如果其中一个 Promise 失败,则以失败状态解析。
- Promise.race 方法用于等待一组 Promise 中率先完成的 Promise,然后以成功状态解析,如果其中一个 Promise 失败,则以失败状态解析。
Promise 的优势
使用 Promise 具有以下优势:
- 简化异步代码: Promise 可以将复杂的异步操作转换为更易读、易维护的同步代码。
- 可串联调用: Promise 的 then 方法允许以可读的方式串联调用异步操作。
- 错误处理: Promise 的 catch 方法提供了一种统一的方式来处理异步操作中的错误。
- 状态管理: Promise 提供了明确的状态管理,可以轻松跟踪异步操作的进度。
常见问题解答
-
Promise 的状态有哪些?
- pending
- fulfilled
- rejected
-
如何处理 Promise 的错误?
- 使用 catch 方法
-
如何等待多个 Promise 完成?
- 使用 Promise.all 方法
-
如何获取率先完成的 Promise?
- 使用 Promise.race 方法
-
Promise 的 finally 方法的作用是什么?
- 无论 Promise 状态如何,都会执行指定的操作