Node.js使用pixelmatch报错:TypeError: listener参数必须是函数
解决Node.js中使用pixelmatch时的
TypeError: "listener" argument must be a function错误 嘿,我一眼就揪出问题所在了——你在给'parsed'事件绑定监听器的时候犯了个新手常踩的小坑:
你写的代码里是这样的:
img1 = fs.createReadStream(screenshot_path).pipe(new PNG()).on('parsed', doneReading())
这里的doneReading()是直接执行了函数,而不是把函数本身作为监听器传递给事件。这就导致事件系统收到的是doneReading执行后的返回值(因为它是async函数,返回的是一个Promise对象),而不是一个可执行的函数,所以才会抛出"listener" argument must be a function这个错误。
第一步:修正监听器绑定
把括号去掉,直接传递函数引用就好:
img1 = fs.createReadStream(screenshot_path).pipe(new PNG()).on('parsed', doneReading) img2 = fs.createReadStream(backup_path).pipe(new PNG()).on('parsed', doneReading)
第二步:处理async函数的潜在问题
你的doneReading是async函数,在事件监听器里用async函数的话,最好加上错误捕获,不然里面的代码抛出错误(比如expect断言失败)时,可能会变成未捕获的Promise拒绝。可以给它包一层try/catch:
let doneReading = async function(){ try { if(++filesRead < 2) return; var diff = new PNG({width: img1.width, height: img2.height}); var numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, img1.width, img1.height, {threshold: 0.1}) diff.pack().pipe(fs.createWriteStream(diff_path)); expect(numDiffPixels).to.equal(0) } catch (err) { // 手动抛出错误,让Mocha能捕获到断言失败或其他异常 throw err; } }
第三步:确保Mocha正确处理异步逻辑
因为compareScreenshots是async函数,在Mocha测试里,只要让函数正常返回Promise就行,Mocha会自动等待Promise完成,不需要额外的done回调。
修正后的完整代码
const fs = require('fs'); const PNG = require('pngjs').PNG; const pixelmatch = require('pixelmatch'); const { expect } = require('chai'); const compareScreenshots = async (path) => { const diff_path = "./build/diff/" + path + ".diff.png" const screenshot_path = "./build/" + path + ".png" const backup_path = "./backup/" + path +".png" // 确保diff目录存在,避免写入失败 fs.mkdirSync('./build/diff/', { recursive: true }); let img1, img2, filesRead = 0; let doneReading = async function(){ try { if(++filesRead < 2) return; // 提前检查图片尺寸,避免pixelmatch报错 if (img1.width !== img2.width || img1.height !== img2.height) { throw new Error(`截图尺寸不匹配:当前截图(${img1.width}x${img1.height}) vs 备份截图(${img2.width}x${img2.height})`); } var diff = new PNG({width: img1.width, height: img2.height}); var numDiffPixels = pixelmatch(img1.data, img2.data, diff.data, img1.width, img1.height, {threshold: 0.1}) diff.pack().pipe(fs.createWriteStream(diff_path)); expect(numDiffPixels).to.equal(0); } catch (err) { throw err; } } // 修正:传递函数引用,而非直接执行函数 img1 = fs.createReadStream(screenshot_path).pipe(new PNG()).on('parsed', doneReading); img2 = fs.createReadStream(backup_path).pipe(new PNG()).on('parsed', doneReading); }
额外小提示
- 我在代码里加了目录检查和尺寸校验,能提前避免一些隐性错误;
- 如果你的测试用例是Mocha的async风格,记得在调用
compareScreenshots时加上await,或者让测试函数返回它的Promise。
内容的提问来源于stack exchange,提问作者A McGuinness
相关产品推荐
相关产品推荐

