2016-11-06 6 views
0

私はnode.jsを学んでいます。私の最初のアプリではとても多くの人が音楽ライブラリを作成していますので、自宅のサーバーからWebブラウザで音楽を聴くことができます。Node.JS asynch call back

私は大丈夫です...しかし、スパゲッティの悪夢をいかに作りたくないかを理解するのは苦労しています。私は約束を守り、これを助けるために非同期ライブラリを使用しています。しかし、私はこの現在のシナリオを持っています。それが完了したときを知る方法を理解しようとしているので、必要なコールバック機能を実行できます。

基本的には、非同期ライブラリを使用してdbとフォルダーの2つの呼び出しを実行しています。そのため、db内のファイルとハードドライブ上のファイルの比較ができます。各非同期メソッドが完了すると、使用している非同期ライブラリによって提供される "完全な"コールバックに戻ります。

この時点で、2つのリストを比較して、dbから見つからないがハードドライブにある音楽ファイルを挿入したいと考えています。グリッドに表示するためにリスト全体をクライアントに送り返したいと思います。

私はこれを行うためにmetamusicdataライブラリを使用しています。そしてここに私のコードは、私がは完全にが行われているファイルをループする際知るためにこれを設定することができますどのように

function(err, results) { 
    console.log("ASYNC COMPLETED"); 
    if (err) $this.callback(err, null); 
    var db = linq.asEnumerable(results.dbList); 
    var files = linq.asEnumerable(results.foldersList); 
    var filesToInsert = db.Where(d => !files.Contains(d.LocFile)); 
    var newMusicList = []; 
    for (var file in filesToInsert) { 
     if (file.indexOf('mp3') || file.indexOf('mp4')) { 
      var fileData = musicMetaData(fs.createReadStream(file), function (err, metadata) { 
       if (err) throw err; 
       newMusicList.push(new Music ({ 
        locFile : file, 
        artist : fileData.artist, 
        album : fileData.album, 
        albumArtist : fileData.albumartist, 
        title : fileData.title, 
        track : fileData.track.no, 
        totalTracks : fileData.track.of, 
        genre : fileData.genre, 
        image : fileData.picture.data, 
        imageType : fileData.picture.format, 
        duration : fileData.duration, 
        createdDate : Date.now(), 
        classification : "unknown" 
       })); 
       console.log(metadata); 
      }); 
     } 
    } 
    //insert into database here the array I created. 
    var insertMyFiles. 
    //query database for the entire list 
    var musicListDb; 
    //return to the callback so it can send the results back to the client browser. 
    return $this.callback(err, musicListDb); 
} 

質問は、これまで(未テスト/完全に完了していない)のですか?だから私は私の配列を作成し、dbに新しいエントリを挿入することができますか?だから私は別のクエリを呼び出して、利用可能な音楽の更新リストを入手できますか?

私は本当にそれをやっている方法を混乱させると考えることができます。 forの代わりにa = iの長さを代入します。最後にmusicmetadataのコールバックでi + 1 = lengthかどうかを確認し、そこにコールバックを呼び出します。

それは私には正しいようではなく、私の目にはむしろスパゲティスです。

私はここで何か解決しないのですか?

+0

なぜダウン誰かが出て、Aとの私の質問に投票ましたそれを改善する方法についてのコメント?理由を知りたい? –

答えて

1

asyncを使用することを検討してください。いわゆる「コールバック地獄」などを取り除くのは本当に簡単です。

+0

私はすでに述べたようにasyncを使用しています。私が取り組んでいる分野は、非同期呼び出しから完成した関数です。そして、そのインスタンスでは、metadatamusicライブラリ呼び出しで、私のために使用する非同期ライブラリを使用する方法はありません。 –

+1

機能が複雑すぎますが、複数の論理的な部分に分割することは可能です。 [このディスカッションについてasync.waterfall](http://stackoverflow.com/questions/25705067/using-async-waterfall-in-node-js) – aring

+0

より良い理解を得るために役立つ追加のリンクありがとうございます。私がしたことは、forループの代わりにasync.eachLimitを使用することでした。私は非同期を使用した場合、私は見つけました。何らかの理由でそれぞれブロックされたioを作成し、応答を劇的に減速させ、スタック内でオーバーフローを引き起こします。基本的には、一度に5つしか処理できないことがわかりました。 –

1

私はそれを約束してください、そして/または、async/awaitを使用します。

非同期/待機は最も簡単です。あなたは通常のforループを持っていますが、あなたのデータを待っています。

あなたはそれはあなたが約束-すべてクリアモジュールやキャッチとちょうどPromise.all(のようなものを使用することができ、並列に実行する必要がある場合)

async function load() { 
    const calls = files.map(async f => { 
    try { return await meta(f) } 
    catch() { return null } 
    }); 
    let metas = await Promise.all(calls); 
    metas = metas.filter(m=>m != null); 
    await insert(metas); 
}