Node.js中for await触发SyntaxError的问题修复请求
问题修复:解决
for await (const chunk of stream)的语法错误 错误根源
你在普通同步生成器函数里使用了for await...of,这是不合法的。for await...of只能在**异步函数(async function)或者异步生成器(async function*)**内部使用,普通生成器的执行上下文是同步的,无法识别await关键字,因此抛出SyntaxError: Unexpected reserved word。
修复方案
需要把依赖异步流的生成器全部改为异步生成器,并同步修改遍历逻辑:
- 将
characters改为异步生成器,让内部可以合法使用for await...of遍历可读流 - 所有依赖异步生成器的后续生成器(
all_words、non_stop_words、count_and_sort)都要改为异步生成器,且内部遍历异步迭代器时要用for await...of - 新增一个异步入口函数来执行最终的统计逻辑
修复后的完整代码
const fs = require('fs'); const stopwords = new Set(fs.readFileSync('../stop_words.txt').toString().split(',').concat(Array.from({ length: 26 }, (_, i) => String.fromCharCode(i + 97)))); // 改为异步生成器 async function* characters(filename) { const stream = fs.createReadStream(filename, { highWaterMark: 1024 }); for await (const chunk of stream) { for (const c of chunk) { yield String.fromCharCode(c); } } } // 改为异步生成器,遍历用for await...of async function* all_words(filename) { let word = ''; for await (const c of characters(filename)) { if (/\w/.test(c)) { word += c.toLowerCase(); } else if (word) { yield word; word = ''; } } if (word) yield word; } // 改为异步生成器,遍历用for await...of async function* non_stop_words(filename) { for await (const w of all_words(filename)) { if (!stopwords.has(w)) { yield w; } } } // 改为异步生成器,遍历用for await...of async function* count_and_sort(filename) { const freqs = {}; let i = 1; for await (const w of non_stop_words(filename)) { freqs[w] = freqs[w] + 1 || 1; if (i % 5000 === 0) { yield Object.entries(freqs).sort((a, b) => b[1] - a[1]); } i++; } yield Object.entries(freqs).sort((a, b) => b[1] - a[1]); } // 新增异步入口函数执行统计 async function run(filename) { // 获取最终排序结果(取最后一次yield的完整统计) let finalResult; for await (const result of count_and_sort(filename)) { finalResult = result; } // 输出频率最高的25个单词 console.log(finalResult.slice(0, 25)); } // 调用示例,替换为你的目标文件路径 run('./your-text-file.txt').catch(err => console.error(err));
关键改动说明
- 所有生成器函数前添加
async关键字,变为异步生成器,这类函数返回异步迭代器,支持for await...of遍历 - 原本同步的
for (const x of ...)全部改为for await (const x of ...),用来遍历异步迭代器 - 新增
run异步函数作为入口,因为异步代码必须在异步上下文里执行,不能直接在全局同步环境中调用异步生成器
内容的提问来源于stack exchange,提问作者Adam Wolf
相关产品推荐
相关产品推荐

