在Nodejs中堆叠异步回调事件的最佳方式

Optimal way for stacking asynchronous callback events in Nodejs

本文关键字:事件 最佳 方式 回调 异步 Nodejs      更新时间:2023-09-26

我正在使用Node和NodeWebkit编写一个本地音乐流应用程序。在我的应用程序中,我扫描音乐文件夹中的任何目录,加载相册艺术,然后用html显示艺术。然而,从开发人员的角度来看,在每个异步回调结束时检测.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'
                                });
                            }
                        });
                    }
                });
        });
    });
});
注意1,Array.forEach是同步的。因此,要初始化flipster,不需要检查最后一个循环的末尾。你可以把它放在循环之后。

注意2,要阅读每个album.json文件,您对该方法有正确的认识。不过,您可能希望使用一个助手,比如async。它通常是为了应对这种情况而存在的。

请检查代码,我用async重写了它。我不能保证它没有错误,但最终的代码应该非常相似。

注意3,最初的fs.readder和对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
}

hth。