如何知道所有的回调都执行完了?可以做下一步操作了
今天用nodejs写了个脚本,主要功能是:
遍历一个文件夹,把在该文件夹下(包括子文件夹)的,长或者宽大于1024像素的图片。以json格式存储这份列表到一个文件中。
这个功能之前用python写了一遍。
现在想练手,所以就用nodejs写了一遍。
期间困扰我最久的问题是:文件的遍历是异步的(不确定是不是异步的回调),获取图片的宽高也是异步的(这个确定是异步的),如何知道所有的回调都执行完了?可以做下一步操作了。刚开始百度到的是用async库,可我太笨了看不懂。
最后算是黑客了一下
process.on('beforeExit', function(code) {
var json = JSON.stringify(file_list,null,2);
fs.writeFileSync(out_dir + "/file_list.json", json_list );
})
在进程结束前的事件中做写文件的事。也是实在没有想到好的办法。
完整代码如下:
var fs = require('fs');
var sharp = require('sharp');//图片处理库
var root_dir = "../res/ui";
var out_dir = "../res/ui";
var file_set = new Array();
var walk = function(file_name){
var states = fs.statSync(file_name);
if(states.isDirectory()){
var files = fs.readdirSync(file_name);
files.forEach(function(file){
walk(file_name + '/' + file)
});
}else if(states.isFile()){
if(file_name.endsWith(".jpg") || file_name.endsWith(".png")){
sharp(file_name).
metadata().
then(function(metadata){
if(metadata.format=="jpeg" || metadata.format=="png"){
if(metadata.width>=1024 || metadata.height>=1024){
file_name = file_name.replace(root_dir+"/","")
//console.log(file_name)
file_set.push(file_name)
}
}
})
}
}
}
//遍历'../res/ui'目录
walk('../res/ui')
process.on('beforeExit', function(code) {
var json_list = JSON.stringify(file_set,null,2);
fs.writeFileSync(out_dir + "/file_list2.json", json_list );
})
6 回复
哨兵变量
哨兵变量
var fs = require('fs');
var sharp = require('sharp');//图片处理库
var Promise = require('bluebird');
var root_dir = "../res/ui";
var out_dir = "../res/ui";
var file_set = new Array();
var key = 0
var after_doThing = function(){
console.log("after_doThing")
var json_list = JSON.stringify(file_set,null,2);
fs.writeFileSync(out_dir + "/file_list2.json", json_list );
}
var doThing = function(file_name){
if(file_name.endsWith(".jpg") || file_name.endsWith(".png")){
key++;
sharp(file_name).
metadata(
function(err,metadata){
key--;
if(metadata.format=="jpeg" || metadata.format=="png"){
if(metadata.width>=1024 || metadata.height>=1024){
file_name = file_name.replace(root_dir+"/","")
//console.log(file_name)
file_set.push(file_name)
}
}
if(key==0){
after_doThing()
}
}
)
}
}
var walk = function(file_name,cb){
var states = fs.statSync(file_name);
if(states.isDirectory()){
var files = fs.readdirSync(file_name);
files.forEach(function(file){
walk(file_name + '/' + file,cb)
});
}else if(states.isFile()){
cb(file_name)
}
}
//遍历'../res/ui'目录
walk('../res/ui',doThing)
我谷歌了一下哨兵变量:大致意思是不是就是下面的代码。
var key = 0
key++;
key--;
if(key==0){
after_doThing()
}
@William17 promise要怎么用啊?感觉好吃力啊-_-!
@dbliu91
哨兵变量有可能会不准确. 假如有深层目录, 在你的代码还在walk深层目录的时候, 其它文件可能已经处理完, 这时key
为0, 事实上还没处理完.
(不过你使用的都是sync方法, 可能不会出现这种问题)
使用Promise
的思路其实也比较简单. 在部分地方使用sync方法简化了代码结构
var fs = require('fs');
/**
* @return {object} Promise
*/
function doThing(fileName) {
// ...
// console.log(fileName);
// do something and return a promise
}
/**
* @return {object} Promise
*/
function walk(fileName, cb) {
var pList = [];
var states = fs.statSync(fileName);
if (states.isDirectory()) {
var files = fs.readdirSync(fileName);
files.forEach(function(file) {
pList.push(walk(fileName + '/' + file, cb));
});
} else if (states.isFile()) {
pList.push(cb(fileName));
}
return Promise.all(pList);
}
walk('filename', doThing).then(function() {
console.log('done');
}).catch(function(err) {
console.log(err);
});