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
相关产品推荐
相关产品推荐

