Promise学习笔记:用通俗易懂的语言,系统掌握异步编程
2023-10-02 10:51:57
异步编程:从阻塞到非阻塞
在传统的同步编程中,程序会逐行执行,直到完成整个操作才继续下一步。而异步编程则不同,它允许程序在等待耗时操作(如网络请求、文件读取等)完成的同时执行其他任务。
Promise:异步编程的利器
Promise是一种用于处理异步操作的 JavaScript 对象。它表示一个最终会完成或失败的异步操作。Promise 提供了统一的 API,简化了异步编程,让我们可以像处理同步操作一样处理异步操作。
Promise 的 API
Promise 的 API 非常简洁,只有三个方法:
then(onFulfilled, onRejected)
:在 Promise 完成或失败时执行指定的回调函数。catch(onRejected)
:在 Promise 失败时执行指定的回调函数。finally(onFinally)
:无论 Promise 完成还是失败,都会执行指定的回调函数。
异常穿透
如果在 Promise 的回调函数中抛出错误,可以通过 .catch()
方法捕获异常。如果未捕获异常,它将穿透到外部作用域,导致 JavaScript 引擎停止运行。
链式调用
Promise 的链式调用是一个非常强大的功能,它允许我们依次执行一系列异步操作。在每个 .then()
回调中,我们可以返回一个新的 Promise,该 Promise 会成为链中下一个操作的输入。
Async 和 Await
Async 和 Await 是 ES2017 引入的语法糖,它们可以简化异步编程。async
函数返回一个 Promise,await
表达式会暂停函数的执行,直到给定的 Promise 完成。
手写 Promise
为了更深入地理解 Promise,我们可以尝试自己手写一个 Promise。这有助于我们理解 Promise 的内部工作原理。
示例代码
// 手写 Promise
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.error = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 执行器函数
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// 成功状态改变
resolve(value) {
if (this.state !== 'pending') return;
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach(callback => callback(value));
}
// 失败状态改变
reject(error) {
if (this.state !== 'pending') return;
this.state = 'rejected';
this.error = error;
this.onRejectedCallbacks.forEach(callback => callback(error));
}
// 添加成功回调
then(onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function') onFulfilled = value => value;
if (typeof onRejected !== 'function') onRejected = error => { throw error; };
const newPromise = new MyPromise(() => {});
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(newPromise, x);
} catch (error) {
rejectPromise(newPromise, error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.error);
resolvePromise(newPromise, x);
} catch (error) {
rejectPromise(newPromise, error);
}
}, 0);
} else {
this.onFulfilledCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
return newPromise;
}
// 添加失败回调
catch(onRejected) {
return this.then(null, onRejected);
}
// 添加 finally 回调
finally(onFinally) {
this.then(
() => onFinally(),
() => onFinally()
);
}
// 处理 Promise 的 resolve 和 reject
static resolve(value) {
return new MyPromise(resolve => resolve(value));
}
static reject(error) {
return new MyPromise((resolve, reject) => reject(error));
}
// Promise 的 all 方法
static all(promises) {
return new MyPromise((resolve, reject) => {
const values = [];
let resolvedCount = 0;
promises.forEach((promise, index) => {
promise.then(value => {
values[index] = value;
resolvedCount++;
if (resolvedCount === promises.length) resolve(values);
}).catch(error => reject(error));
});
});
}
// Promise 的 race 方法
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
promise.then(resolve, reject);
});
});
}
}
总结
Promise 是异步编程中的重要工具,它使我们能够优雅地处理异步操作。通过了解 Promise 的 API、异常穿透、链式调用以及手写 Promise,我们可以更深入地理解异步编程的原理。掌握 Promise 有助于我们编写出更健壮、更易于维护的 JavaScript 代码。