2016-11-06 4 views
0

Я просто изучаю node.js, поэтому для своего первого приложения, как и многие люди, я создаю музыкальную библиотеку, чтобы я мог слушать музыку через веб-браузер с моего сервера дома.Node.JS asynch call back

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

В сущности, я использовал асинхронную библиотеку, чтобы сделать два вызова один на db и один в папку, чтобы я мог сравнивать файлы, которые у меня есть в db, с теми, что указаны на жестком диске. После выполнения каждого метода асинхронизации он возвращается к «полному» обратному вызову, предоставляемому асинхронной библиотекой, которую я использую.

На этом этапе я хочу выполнить сравнение двух списков и вставить музыкальные файлы, отсутствующие в 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 in на a для i = для длины. затем в обратном вызове для musicmetadata в конце проверки, чтобы увидеть, если i + 1 = длина, если так, то вызовите обратный вызов внутри.

Это не кажется правильным для меня и является довольно spagettish в моих глазах.

Какое решение я не вижу или не понимаю здесь?

+0

Так почему же кто-то вниз голосовать на мой вопрос с вне комментарий о том, как его улучшить? Как знать, почему? –

ответ

1

Рассмотрите возможность использования async, с ним действительно легко избавиться от так называемого «обратного ад» и многое другое.

+0

Я уже использую async, как я уже говорил. Область, над которой я работаю, - это завершенная функция из асинхронного вызова. И в этом случае я не вижу возможности использовать библиотеку async, которая будет использоваться для меня с вызовом библиотеки метаданных. –

+1

Ваша функция слишком сложна, и все же вы можете разделить ее на несколько отдельных логических фрагментов. Проверьте [это disqussion about async.waterfall] (http://stackoverflow.com/questions/25705067/using-async-waterfall-in-node-js) – aring

+0

благодарим вас за дополнительную ссылку, которая была полезна для лучшего понимания. .. То, что я сделал, было использовать async.eachLimit вместо цикла for. Я нашел, если я использовал async.Каждый по какой-то причине он создавал бы заблокированный io и резко замедлял бы ответ, а также зависал бы с потоком в стеке. В основном я обнаружил, что могу обрабатывать только 5 штук. –

1

Для этого я использую обещания и/или асинхронные/ждущие.

Async/await является самым простым. У вас просто нормальный цикл, но жду ваших данных.

Если вам это нужно, чтобы работать параллельно вы можете использовать что-то вроде обещания, отбоя модуль или просто 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); 
}  

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

  • Нет связанных вопросов^_^