Javascript 在Nodejs中堆叠异步回调事件的最佳方法
我正在使用Node和NodeWebkit编写一个本地音乐流应用程序。在我的应用程序中,我扫描音乐文件夹中的任何目录,加载相册艺术,然后用html显示艺术。但是,从开发人员的角度来看,在每个异步回调结束时检测Javascript 在Nodejs中堆叠异步回调事件的最佳方法,javascript,node.js,asynchronous,node-webkit,asynccallback,Javascript,Node.js,Asynchronous,Node Webkit,Asynccallback,我正在使用Node和NodeWebkit编写一个本地音乐流应用程序。在我的应用程序中,我扫描音乐文件夹中的任何目录,加载相册艺术,然后用html显示艺术。但是,从开发人员的角度来看,在每个异步回调结束时检测.forEach()迭代器结束的逻辑并不能生成干净的代码。从逻辑上讲,它是可行的,但如果我要解开这串依赖关系,我就必须重写所有的依赖关系 以下是我的代码片段: // Fetch the music albums fs.readdir("./music", function(err, file
.forEach()
迭代器结束的逻辑并不能生成干净的代码。从逻辑上讲,它是可行的,但如果我要解开这串依赖关系,我就必须重写所有的依赖关系
以下是我的代码片段:
// Fetch the music albums
fs.readdir("./music", function(err, files) {
if (err) {
//return console.error(err);
}
//document.write(JSON.stringify(files));
// Look specifically for music album folders (directories)
filterDirectories("./music", files, function(dirs){
dirs.forEach(function(dir, index, array){
fs.readFile('./music/' + dir + "/album.json", 'utf-8', function (err, data) {
data = JSON.parse(data);
if (err) {
return console.error(err);
}
// Create a li item for every album, and append it to the unordered list
var li = $('<li><img /><a target="_blank"></a></li>');
li.find('a')
.attr('href', '#')
.text(data.album_name);
li.find('img').attr('src', './music/' + dir + '/' + data.album_art_loc).css('width:512px;height:512px;');
lis.push(li);
// Is this the last album folder?
if(index == array.length-1) {
// Go through the array
lis.forEach(function(item, index, array){
// add to the ul element
item.appendTo(ul);
// Have we added the last one to the ul element?
if(index == array.length - 1){
// Ok, now we initialize the flipster plugin to make it look 3D and advanced
$('.flipster').flipster({
style: 'carousel'
});
}
});
}
});
});
});
});
//获取音乐专辑
fs.readdir(“./music”,函数(错误,文件){
如果(错误){
//返回控制台。错误(err);
}
//document.write(JSON.stringify(files));
//专门查找音乐专辑文件夹(目录)
过滤器目录(“./音乐”、文件、函数(目录){
dirs.forEach(函数(dir、index、数组){
fs.readFile('./music/'+dir+“/album.json”,'utf-8',函数(err,data){
data=JSON.parse(数据);
如果(错误){
返回控制台。错误(err);
}
//为每个相册创建一个li项,并将其附加到无序列表中
var li=$('注1,Array.forEach是同步的。因此,要初始化flipster,不需要检查最后一个循环的结尾。只需将它放在循环的正后方即可
注意2,要读取每个album.json文件,您对该方法有正确的认识。不过,您可能希望使用一个帮助程序,例如。它通常用于处理此类情况
请检查代码,我用async重写了它。我不保证它没有bug,但最终的代码应该非常相似
注意3,初始的fs.readdir和对filterDirectories的调用似乎可以合并到一个异步函数中
注4,可能值得一读
代码重写
var async = require('async')
var musicFiles;
var musicDirs;
var lis = [];
async.series([
function (next) {
fs.readdir("./music", function(err, files) {
if (err) next(err);
musicFiles = files;
next();
});
},
function (next) {
filterDirectories("./music", files, function(dirs){
musicDirs = dirs;
next();
});
},
function (next) {
var todos = [];
musicDirs.forEach(function(dir){
todos.push(function (nextTodo) {
fs.readFile('./music/' + dir + "/album.json", 'utf-8', function (err, data) {
if (err) nextTodo(err);
lis.push(createLi(JSON.parse(data)));
nextTodo();
});
})
});
async.parallelLimit(todos, 4, next);
},
function (next) {
lis.forEach(function(li){
li.appendTo(ul);
});
$('.flipster').flipster({
style: 'carousel'
});
}
], function () {
console.log("All done !")
})
function createLi (data) {
var li = $('<li><img /><a target="_blank"></a></li>');
li.find('a')
.attr('href', '#')
.text(data.album_name);
li.find('img').attr('src', './music/' + dir + '/' + data.album_art_loc).css('width:512px;height:512px;');
return li
}
var async=require('async')
音乐档案;
var musicDirs;
var-lis=[];
异步系列([
功能(下一个){
fs.readdir(“./music”,函数(错误,文件){
如果(错误)下一个(错误);
音乐文件=文件;
next();
});
},
功能(下一个){
过滤器目录(“./音乐”、文件、函数(目录){
musicDirs=dirs;
next();
});
},
功能(下一个){
var todos=[];
musicDirs.forEach(函数(dir){
todos.push(功能(下一步){
fs.readFile('./music/'+dir+“/album.json”,'utf-8',函数(err,data){
如果(错误)下一步做(错误);
lis.push(createLi(JSON.parse(data));
nextTodo();
});
})
});
parallelLimit(todos,4,next);
},
功能(下一个){
lis.forEach(功能(li){
li.附录(ul);
});
$('.flipster')。flipster({
风格:“旋转木马”
});
}
],函数(){
log(“全部完成!”)
})
函数createLi(数据){
变量li=$('
hth.lis在哪里初始化?if(index==array.length-1){
应该如何工作?我建议看一下promises。您还将浏览器代码与Node.js代码混合使用。@djfdev NWjs@Bergi lis在应用程序顶部被进一步初始化。lis=[]
。当索引计数器到达列表中的最后一个元素时,我们知道我们已经获取了该相册中的所有信息。但是我发现这并不总是正确的,因为它是异步的。这就是答案。我能够对该解决方案做一些小的调整,我的代码与以前完全一样,现在它是结构化的d可读。