2016-05-05 15 views
1

Ich schreibe eine lokale Musik-Streaming-App mit Node und NodeWebkit. In meiner App scanne ich den Musikordner nach Verzeichnissen, lade das Albumcover und zeige dann die Grafik in HTML an. Die Logik zum Erkennen des Endes von .forEach() Iteratoren am Ende jedes asynchronen Rückrufs macht jedoch aus Sicht des Entwicklers keinen sauberen Code. Logischerweise funktioniert es, aber wenn ich diese Reihe von Abhängigkeiten entwirren würde, müsste ich alles neu schreiben.Optimale Möglichkeit zum Stapeln von asynchronen Callback-Ereignissen in Nodejs

Hier ist ein Ausschnitt aus meinem Code:

// 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

Wo wird 'lis' initialisiert? Wie soll 'if (index == array.length-1) {' funktionieren? – Bergi

+4

Ich empfehle, sich Versprechungen anzusehen. – Bergi

+0

Sie mischen auch Browsercode mit Node.js-Code. – djfdev

Antwort

1

Note 1 ist Array.ForEach synchron. Um Flipster zu initialisieren, müssen Sie also nicht das Ende der letzten Schleife überprüfen. Sie können es einfach nach der Schleife setzen.

Hinweis 2, um jede album.json Datei zu lesen, haben Sie Recht über die Methode. Vielleicht möchten Sie einen Helfer wie async verwenden. Das gibt es normalerweise, um mit solchen Situationen umzugehen.

Bitte überprüfen Sie den Code, ich schrieb es mit Async um. Ich garantiere nicht, dass es fehlerfrei ist, aber der endgültige Code sollte sehr ähnlich sein.

Hinweis 3 scheint die anfängliche fs.readdir und der Aufruf für filterDirectories in eine async-Funktion zusammenführbar.

Note 4, kann es sich lohnen this

Code Rewrite lesen

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

Das war die Antwort. Ich konnte kleinere Änderungen an dieser Lösung vornehmen und mein Code funktionierte genauso wie zuvor und jetzt ist er strukturiert und lesbar. – Maverick