1

私はノードと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などのヘルパーを使用することもできます。この種の状況に対処するために通常存在します。

コードを確認してください。私はasyncを使用して書き換えました。私はそれがバグフリーであることを保証しませんが、最終的なコードは非常に似ているはずです。

注3、最初のfs.readdirとfilterDirectoriesの呼び出しは、1つの非同期関数にマージ可能であるようです。

注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