You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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。

修复方案

需要把依赖异步流的生成器全部改为异步生成器,并同步修改遍历逻辑:

  1. 将characters改为异步生成器,让内部可以合法使用for await...of遍历可读流
  2. 所有依赖异步生成器的后续生成器(all_words、non_stop_words、count_and_sort)都要改为异步生成器,且内部遍历异步迭代器时要用for await...of
  3. 新增一个异步入口函数来执行最终的统计逻辑

修复后的完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:52:04