你的浏览器无法正常显示内容,请更换或升级浏览器!

Node.js 异步编程常见错误与最佳实践

tenfei
tenfei
发布于2026-08-21 14:49 阅读12次
Node.js 异步编程常见错误与最佳实践
梳理 Node.js 异步编程中最常见的错误和最佳实践,涵盖回调地狱、Promise 链、async/await 错误处理、并发控制、内存泄漏等,附代码对比示例,帮助开发者写出健壮的异步代码。
# Node.js 异步编程常见错误与最佳实践 ## 前言 Node.js 的核心是异步,但异步也最容易埋坑:回调地狱、错误被吞、并发失控。本文梳理最常见的异步编程错误和对应的最佳实践。 ## 错误1:回调地狱 ```javascript // 错误:层层嵌套 getUser(id, (err, user) => { getOrders(user.id, (err, orders) => { getDetails(orders[0].id, (err, details) => { // 深层嵌套,难以维护 }); }); }); // 正确:async/await const user = await getUser(id); const orders = await getOrders(user.id); const details = await getDetails(orders[0].id); ``` ## 错误2:忘记 await ```javascript // 错误:promise 未 await,结果 undefined async function main() { const result = fetchData(); // 漏了 await console.log(result); // Promise 对象,不是数据 } // 正确 const result = await fetchData(); ``` 可以用 ESLint 的 `require-await` 和 `no-floating-promises` 规则提前发现。 ## 错误3:错误处理不完整 ```javascript // 错误:try-catch 只包了一部分 async function main() { const user = await getUser(id); // 这行可能抛错 try { const orders = await getOrders(user.id); } catch (err) { console.log(err); } } // 正确:统一 try-catch 或错误边界 async function main() { try { const user = await getUser(id); const orders = await getOrders(user.id); } catch (err) { console.error(err); // 记录日志、返回错误响应 } } ``` ## 错误4:循环中的串行 await ```javascript // 错误:循环里 await,串行执行,慢 for (const id of ids) { await process(id); } // 正确:Promise.all 并发执行 await Promise.all(ids.map(id => process(id))); // 注意:Promise.all 有一个失败全失败, // 需要容错用 allSettled const results = await Promise.allSettled(ids.map(process)); ``` ## 错误5:并发无限制 ```javascript // 危险:同时发起 1 万个请求,打爆资源 await Promise.all(hugeList.map(fetch)); // 正确:限制并发数 async function mapLimit(items, limit, fn) { const results = []; const queue = [...items]; async function worker() { while (queue.length) { const item = queue.shift(); results.push(await fn(item)); } } await Promise.all(Array(limit).fill().map(worker)); return results; } await mapLimit(hugeList, 10, fetch); ``` ## 错误6:事件监听器累积 ```javascript // 错误:每次调用都添加监听器 function setup() { emitter.on("data", handler); } // 正确:用 once 或显式移除 emitter.once("data", handler); // 或 emitter.on("data", handler); emitter.off("data", handler); ``` ## 最佳实践总结 ### 统一错误处理中间件 ```javascript // Express 全局错误处理 app.use((err, req, res, next) => { console.error(err); res.status(500).json({ error: "Internal Server Error" }); }); // 全局捕获未处理的 Promise 异常 process.on("unhandledRejection", (reason) => { console.error("Unhandled Rejection:", reason); }); ``` ### 超时控制 ```javascript function withTimeout(promise, ms) { return Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), ms) ), ]); } await withTimeout(fetchData(), 5000); ``` ## 小结 异步编程的关键:用 async/await 替代回调、始终处理错误、控制并发数、避免循环串行。记住 Promise.all 和 allSettled 的区别,配合超时控制和全局错误处理,代码健壮性会大幅提升。

2

0

文章点评
Copyright © from 2021 by namoer.com
458815@qq.com QQ:458815
蜀ICP备2022020274号-2