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

Electron主进程中如何存储两个Cheerio解析对象并同步比较?

解决Electron主进程中Cheerio解析HTML后无法存储并调用方法的问题

问题根源

你遇到的核心问题是**fs.readFile是异步操作**,你写的比较代码在两个文件还没读取完成、comparedBodyA和comparedBodyB还未被赋值时就已经执行了,此时这两个变量都是undefined,调用.find()自然会报错。另外,两个读取回调里的var $会存在覆盖风险,且异步执行顺序不确定也会影响结果。

修正方案

改用fs.promises.readFile(Node.js 10+支持,返回Promise)结合async/await来保证操作顺序,等两个文件都读取并解析完成后再执行比较。同时为每个HTML文件保留独立的Cheerio实例,避免变量覆盖。

修正后的代码

const {
  app,
  Menu,
  shell,
  ipcMain,
  BrowserWindow,
  globalShortcut,
  dialog
} = require('electron');
const fs = require('fs').promises; // 使用Promise版文件操作
const cheerio = require('cheerio');

const UpdatedFromDailyFeedFile = "UpdatedFromDailyFeedFile.html";
const StorageFileCustomizedBasedOnTemplate = "index.html";

// 封装HTML解析函数
async function parseHtmlFile(filePath) {
  try {
    const data = await fs.readFile(filePath);
    return cheerio.load(data.toString(), { decodeEntities: false });
  } catch (err) {
    console.error(`读取文件${filePath}失败:`, err);
    throw err;
  }
}

// 核心比较逻辑
async function compareHtmlLists() {
  try {
    // 依次读取并解析两个HTML文件
    const $a = await parseHtmlFile(UpdatedFromDailyFeedFile);
    const $b = await parseHtmlFile(StorageFileCustomizedBasedOnTemplate);

    // 处理第二个文件的JS链接添加逻辑
    const jsFileOfHTML = './index.js';
    if ($b('body').find('#js-script-link').length === 0) {
      $b('body').append(`<script id="js-script-link" src="${jsFileOfHTML}"></script>`);
      // 如需将修改后的HTML写回文件,可取消下面注释
      // await fs.writeFile(StorageFileCustomizedBasedOnTemplate, $b.html());
    }

    // 获取目标列表
    const comparedListA = $a('body').find('ul.section.img-text').eq(2);
    const comparedListB = $b('body').find('ul.section.img-text').eq(2);

    // 执行内容比较
    comparedListA.each(function (index) {
      const firstLi = $a(this);
      const secondLi = comparedListB.eq(index);

      if (firstLi.html() === secondLi.html()) {
        console.log(`same: ${firstLi.html()}`);
      } else {
        console.log(`different first: ${firstLi.html()} second: ${secondLi.html()}`);
      }
    });
  } catch (err) {
    console.error('比较过程出错:', err);
  }
}

// 在Electron应用初始化完成后执行比较
app.whenReady().then(() => {
  compareHtmlLists();
  // 其他Electron初始化逻辑...
});

关键改动说明

  • 用fs.promises.readFile替代回调版API,配合async/await确保文件读取和解析顺序执行,彻底解决异步导致的变量未赋值问题。
  • 为每个HTML文件分配独立的Cheerio实例($a和$b),避免变量覆盖,确保操作对应正确的DOM树。
  • 将比较逻辑封装在独立函数中,统一处理错误,避免未捕获异常。
  • 把比较逻辑放在app.whenReady()回调中,确保Electron应用环境初始化完成后再执行文件操作。

内容的提问来源于stack exchange,提问作者Rick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:35:37