Node.js中Jimp循环执行时随机抛出Could not find MIME for Buffer <null>错误
问题原因分析
- 异步操作顺序混乱:
takeScreenshot里的image.write('test-screenshot.png')是异步方法,但你在调用它之后立刻打印"Saved...",实际这时候文件还没写完。而convertScreenshot紧接着执行,去读取这个可能还未写入完成的文件,就会出现读入空Buffer的情况,触发Could not find MIME for Buffer <null>错误。 - 循环执行的叠加问题:每2秒一次的
foo()调用会重复触发读写操作,旧的读写操作还没完成,新的又开始,进一步加剧了文件资源的竞争,导致错误随机出现。
修复方案
方案1:严格控制异步操作顺序
把takeScreenshot包装成Promise,确保文件写入完成后再执行转换操作:
const Jimp = require("jimp"); function takeScreenshot() { // 声明变量避免全局污染 const x=35, y=11, width=180, height=17; const img = robot.screen.capture(x, y, width, height).image; return new Promise((resolve, reject) => { new Jimp({data: img, width, height}, (err, image) => { if (err) return reject(err); // 使用Jimp的writeAsync方法返回Promise image.writeAsync('test-screenshot.png') .then(() => { console.log("Saved..."); resolve(); }) .catch(reject); }); }); } async function convertScreenshot() { try { console.log("converting..."); const image = await Jimp.read('test-screenshot.png'); await image.contrast(0.8).writeAsync('test-contrastScreenshot.png'); } catch(error) { console.log(error); } } async function foo() { // 先等待截图保存完成,再执行转换 await takeScreenshot(); await convertScreenshot(); setTimeout(foo, 2000); } foo();
方案2:避免文件覆盖(可选)
给每个截图文件添加时间戳后缀,彻底避免读写冲突:
const Jimp = require("jimp"); function takeScreenshot() { const timestamp = Date.now(); const fileName = `test-screenshot-${timestamp}.png`; const x=35, y=11, width=180, height=17; const img = robot.screen.capture(x, y, width, height).image; return new Promise((resolve, reject) => { new Jimp({data: img, width, height}, (err, image) => { if (err) return reject(err); image.writeAsync(fileName) .then(() => { console.log(`Saved ${fileName}...`); resolve(fileName); }) .catch(reject); }); }); } async function convertScreenshot(fileName) { try { console.log("converting..."); const image = await Jimp.read(fileName); const outputName = fileName.replace('.png', '-contrast.png'); await image.contrast(0.8).writeAsync(outputName); } catch(error) { console.log(error); } } async function foo() { const fileName = await takeScreenshot(); await convertScreenshot(fileName); setTimeout(foo, 2000); } foo();
额外注意事项
- 变量必须用
const/let声明,原代码中x、y等变量未声明会成为全局变量,可能引发其他隐性问题。 - 优先使用Jimp提供的
writeAsync这类返回Promise的方法,比回调写法更易维护和控制流程。
内容的提问来源于stack exchange,提问作者Genesis1337
相关产品推荐
相关产品推荐

