应使用块级 try-catch 隔离单次迭代副作用:每次迭代用独立代码块包裹,let/const 变量不泄漏,全局状态更新仅在 try 块内执行,catch 中避免同步修改共享状态,异步迭代需为每个 await 单独捕获。

在使用迭代器(如 for...of、Array.prototype.forEach 或自定义迭代逻辑)遍历异步/不可靠数据源时,若某次迭代中抛出未捕获异常,不仅会中断循环,还可能因错误处理缺失,导致页面级状态树(如 Vuex/Pinia/Redux 的 store、React 的全局 context、或裸写的 window.state)被意外修改或残留脏数据。巧用 try-catch 的块级作用域隔离性,可将单次迭代的副作用严格限制在自身作用域内,避免污染共享状态。
利用块级 try-catch 隔离单次迭代副作用
JavaScript 中每个 try-catch 语句本身不创建新作用域,但配合 {} 显式块和 let/const 声明,就能实现逻辑与变量的双重隔离:
- 每次迭代用独立代码块包裹,内部声明的
let变量不会泄漏到外层; -
catch捕获后仅处理当前项错误,不影响后续迭代; - 关键:所有对全局状态树的写操作(如
store.commit、setState)必须放在try块内完成——成功才更新,失败则跳过,杜绝“半更新”状态。
避免在 catch 中误写全局状态
常见误区是把错误兜底逻辑(如记录日志、上报、设置 fallback 值)直接写进 catch 并同步更新全局状态,这反而引入新污染点:
- 不要在
catch里调用store.dispatch('setError', ...)—— 错误是局部的,不应覆盖全局错误字段; - 若需记录,用局部变量暂存错误信息,循环结束后统一聚合上报;
- 绝不给全局状态赋默认值(如
state.items = []),除非你明确要清空整个列表。
结合 await + try-catch 处理异步迭代
对 async 迭代器(如 for await...of),必须为每次 await 单独加 try-catch,否则一个 Promise reject 会直接跳出整个循环:
for (const item of items) {
try {
const data = await fetchItem(item.id); // 每次请求独立捕获
store.commit('addItem', data); // 成功才提交
} catch (err) {
console.warn(`跳过 item ${item.id}:`, err.message);
// 不修改 store,不 throw,继续下一轮
}
}
用 IIFE 或函数封装强化隔离(进阶)
当迭代体逻辑复杂、涉及多个状态更新点时,可用立即执行函数表达式(IIFE)进一步收紧作用域:
- 把整段处理逻辑封装进
(() => { ... })(),内部所有let、const完全私有; - IIFE 内部
try-catch更清晰表达“这一组操作要么全成,要么全败,且不牵连外部”; - 适合需要临时计算中间状态、多步校验后再批量提交的场景。

















