1

Я пишу местное приложение для потоковой передачи музыки с использованием Node и NodeWebkit. В моем приложении я просматриваю папку с музыкой для любых каталогов, загружаю обложку альбома, а затем показываю искусство в html. Однако логика обнаружения конца итераторов .forEach() в конце каждого асинхронного обратного вызова не делает чистый код с точки зрения разработчиков. Логически это работает, но если бы я должен был распутать эту строку зависимостей, мне пришлось бы переписать все это.Оптимальный способ для хранения асинхронных событий обратного вызова в Nodejs

Вот отрывок из моего кода:

// 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' 
           }); 
          } 
         }); 
        } 
       }); 
     }); 
    }); 
}); 
+0

Где находится 'lis'? Как 'if (index == array.length-1) {' должен работать? – Bergi

+4

Я рекомендую взглянуть на обещания. – Bergi

+0

Вы также смешиваете код браузера с кодом Node.js. – djfdev

ответ

1

примечание 1, Array.forEach синхронно. Поэтому для инициализации флипстера вам не нужно проверять конец последнего цикла. Вы можете просто положить это прямо после цикла.

примечание 2, чтобы прочитать каждый файл album.json, у вас есть право на метод. Хотя, возможно, вы захотите использовать помощника, такого как async. Что обычно существует, чтобы справляться с такими ситуациями.

Проверьте код, я переписал его с помощью асинхронного вызова. Я не гарантирую, что это ошибка, но окончательный код должен быть очень похож.

примечание 3, исходный fs.readdir и вызов для filterDirectories кажется объединенным в одну асинхронную функцию.

примечание 4, может стоит читать this

кодовым перепишет

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.

+0

Это был ответ. Я смог внести небольшие корректировки в это решение, и мой код работал точно так же, как и раньше, и теперь он структурирован и доступен для чтения. – Maverick

Смежные вопросы