编写异步 JavaScript 的 10 种最佳实践以及解释和编码示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
1. 拥抱 Promises 或 Async/Await 控制流:
问题:传统的回调可能导致“回调地狱”,使代码难以阅读和维护。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
Promises:使用 .then() 和 .catch() 方法提供更清晰的方法来处理异步操作。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
function fetchData(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => resolve(JSON.parse(xhr.responseText));
xhr.onerror = reject;
xhr.send();
});
}
fetchData('https://api.example.com/data')
.then(data => console.log(data))
.catch(error => console.error(error));
Async/Await:Promise 之上的语法糖,提供更像同步的感觉。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
async function fetchData(url) {
const response = await fetch(url);
const data = await response.json();
return data;
}
(async () => {
try {
const data = await fetchData('https://api.example.com/data');
console.log(data);
} catch (error) {
console.error(error);
}
})();
2. 利用 fetch 进行现代异步操作:
问题:旧的 XMLHttpRequest (XHR) API 更加冗长。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:使用 fetch API,提供更简洁且基于 Promise 的方法。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
3. 优雅地处理错误:
问题:未处理的错误可能会使您的应用程序崩溃。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:将 .catch() 与 Promises 结合使用,或将 try...catch 与 async/await 结合使用来管理错误。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
(async () => {
try {
const data = await fetchData('https://api.example.com/data');
console.log(data);
} catch (error) {
console.error('Error fetching data:', error);
}
})();
4.考虑使用异步迭代器进行流处理:
问题:如果立即处理,大数据集可能会使浏览器不堪重负。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:使用异步迭代器(如由response.body.getReader()返回的迭代器)来处理块中的数据。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
async function processDataStream(stream) {
const reader = stream.getReader();
let result = ‘’;
while (!(await reader.closed)) {
const { done, value } = await reader.read();
result += value ? new TextDecoder().decode(value) : ‘’;
if (done) {
break;
}
}
console.log(result);
}
fetch(‘https://api.example.com/large-data’)
.then(response => processDataStream(response.body))
.catch(error => console.error(error));
5. 对长时间运行的操作采用取消:
问题:如果用户离开,长时间运行的操作可能会变得过时。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:利用 AbortController API 创建取消信号。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
const controller = new AbortController();
const signal = controller.signal;
fetch('https://api.example.com/long-running', { signal })
.then(response => response.json())
.then(data => console.log(data))
.catch(error => {
if (error.name === 'AbortError') {
console.log('Operation cancelled');
} else {
console.error(error);
}
});
// Simulate user navigation (cancelling the request)
controller.abort();
6. 性能优化:去抖和节流
问题:频繁的事件处理程序(例如,按键时)可能会触发不必要的请求。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:Debounce:延迟操作,直到自上次事件以来经过一定时间。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
7. 利用生成器进行复杂的异步工作流程:
问题:具有多个异步操作的复杂逻辑可能变得难以管理。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:生成器(带有yield的函数)可用于暂停和恢复执行,使代码更具可读性。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
async function* fetchDataInParts(url) {
const response = await fetch(url);
for await (const chunk of response.body) {
yield chunk;
}
}
(async () => {
for await (const chunk of fetchDataInParts('https://api.example.com/large-data')) {
console.log(new TextDecoder().decode(chunk));
}
})();
8. 探索异步/等待与并行执行:
问题:您可能想要同时执行多个异步操作。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:虽然 async/await 本质上是顺序的,但请使用 Promise.all() 或 async.parallel(来自外部库)并行运行操作。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
async function fetchData1(url) {
// ... fetch data from URL 1
}
async function fetchData2(url) {
// ... fetch data from URL 2
}
(async () => {
const [data1, data2] = await Promise.all([fetchData1('url1'), fetchData2('url2')]);
console.log(data1, data2);
})();
9. 考虑复杂数据流的可观察量:
问题:异步数据流可能需要复杂的逻辑和订阅。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:Observables(例如,来自 RxJS)提供了一种强大的方法来使用用于转换和操作的运算符来处理数据流。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
10.彻底测试您的异步代码:
问题:由于异步代码的非阻塞性质,测试起来可能很棘手。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
解决方案:利用 Jest 或 Mocha 等具有模拟功能的库来测试不同的场景,包括错误处理和边缘情况。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html通过遵循这些最佳实践,您将能够很好地编写干净、可维护且高效的异步 JavaScript 代码!文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/63469.html