检查文件是否完全用node.js写入

我需要一些帮助,我可以如何处理JavaScript中的下列任务:我有一个应用程序,使用Jimp进行image processing和节点 – 精灵生成器。 这一切都运行在node.js上下文中。 我把一些图像加载到Jimp,用图像做一些东西,然后用nodejs filemodule把它写回到我的文件系统。 然后,我将采取新的创build的图像,并将其粘贴到节点 – 精灵发生器。 问题是,目前并不是所有的图像都被创build/写入。 创buildSpritesheet的代码在Jimp返回后立即运行,我认为Jimp处理所有的图像并返回一个promise。 结果是,创buildspritesheet的代码被执行,但堆栈没有完成。

我试着用fs.stat()和properties的时间来testing这个文件是否写入

if (stat.mtime.getTime() === prev.mtime.getTime()) 

但是这时可能会发生错误,此时文件没有被创build。 另外:我需要一种方式来检查图像是否完全写入处理,当图像的path是当前不可用。

 function resize(img) { Jimp.read(img.path).then(function (err, file) { if (err) throw err; file.resize(200, 200) .quality(70) .write(newPath); //newPath for simplicity }); } function rec(imgObjArray) { if(_.isEmpty(imgObjArray)) return; resize(imgObjArray.pop()); //correct mistake in function call from fn() to rec() rec(imgObjArray); } rec(imgObjArray); //imgObjArray === [img,img,img....] //nsg() does not work because not all images are written at this time nsg({ src: [ 'out/images/desktop/*.jpg' ], spritePath: 'out/images/desktop/sprite.jpg',, compositor: 'jimp' }, function (err) { console.log('Sprite generated!'); }) 

我认为首先我必须检查图像是否存在于给定的path,然后检查写入是否完成。 但是当我用fs.access(path [,mode],callback)创build一个fn并且这个文件没有被创build的时候,我得到一个错误。

在这里你已经混合了同步代码和asynchronous代码。 我将尝试描述评论中发生的事情:

首先,你的函数定义 – 你正在触发asynchronous操作,没有正确处理完成

 // I've re-spaced the code slightly and removed your comments so mine stand out function resize(img) { Jimp.read(img.path).then(function (err, file) { // this code only executes after the file is done reading, but this // is an asynchronous action - it doesn't hold up execution if (err) throw err; file.resize(200, 200).quality(70).write(newPath); // .write() is presumably *also* an asynchronous action - if you want // something to happen only *after* it's been written, it needs to be in // a callback or promise on the write method }); // I added this explicitly - after you *start* your Jimp.read, you *immediately* // return from this function, *before* the read is completed. If you want // something to happen only *after* your read and write, you either need to // return the promise so you can act on it, or put the further actions in a callback return undefined; } function rec(imgObjArray) { if(_.isEmpty(imgObjArray)) return; // resize() runs and returns *before* the file is read, resized, and written resize(imgObjArray.pop()); // I don't know what fn() is, it's not defined here - presumably it's not important fn(imgObjArray); } 

然后,你的程序调用:

 // this fires off and completes immediately, having initiated the asynchronous methods rec(imgObjArray); // you call this on the assumption that all of your code above has completed, but since // it's asynchronous, that's not true, you get here with *none* of your images completed nsg({ src: [ 'out/images/desktop/*.jpg' ], spritePath: 'out/images/desktop/sprite.jpg', compositor: 'jimp' }, function (err) { console.log('Sprite generated!'); }); 

你有两个select:

如果file.write()是一个同步调用,那么你可以直接返回promise,并对其执行操作:

 function resize(img) { // by *returning* this call, we're actually returning the promise, we can act on // in the future return Jimp.read(img.path).then(function (err, file) { if (err) throw err; file.resize(200, 200).quality(70).write(newPath); }); } function rec(imgObjArray) { if(_.isEmpty(imgObjArray)) return; // the result of resize is now a promise return resize(imgObjArray.pop()).then(function(err) {; // again, assuming `fn()` is synchronous... fn(imgObjArray); }); } // now the result of *this* call is a promise, which you can use to control // the timing of your next call rec(imgObjArray).then(function(err) { // now this will only run after all of the previous calls have executed nsg({ src: [ 'out/images/desktop/*.jpg' ], spritePath: 'out/images/desktop/sprite.jpg', compositor: 'jimp' }, function (err) { console.log('Sprite generated!'); }); }); 

…如果承诺的语法不正确,我没有积极使用节点,因为它们变得无处不在。

即使你的子调用是asynchronous的,也有可能以同样的方式使用promise,但是我没有那么做。

否则,您可以将callback传递给您的函数:

 function resize(img, cb) { // ... you get the idea... file.resize(200, 300).quality(70).write(newPath, cb); } function rec(imgObjArray, cb) { // ... you get the idea... resize(imgObjArray.pop(), cb); } rec(imgObjArray, function(err, response) { nsg({ src: [ 'out/images/desktop/*.jpg' ], spritePath: 'out/images/desktop/sprite.jpg', compositor: 'jimp' }, function (err) { console.log('Sprite generated!'); }); }); 

希望这可以帮助!