Вложенные асинхронные функции - PullRequest
0 голосов
/ 08 января 2019

Я создаю сценарий для сбора трек-листа на каждый релиз из Discogs. Мой getTracklist выполняется после getLabelReleases. Проблема здесь в том, что он должен выполняться, пока работает над конкретным выпуском. (таким образом, список дорожек массива может быть заполнен соответствующими дорожками)

Как я могу это исправить, и кто-нибудь может объяснить, что происходит?

 function getLabelReleases(label, callback) {
   label['releases'] = [];

   var db = new Discogs().database();
   db.getLabelReleases(label.id, function(err, data){
       //console.log(JSON.stringify(data, null, 2));

       data.releases.forEach(function(release, index) {
         //console.log(pretty(release));
         label['releases'][index]= {};

         label['releases'][index]['order']=index+1;
         label['releases'][index]['id']=release.id;
         label['releases'][index]['catno']=release.catno;
         label['releases'][index]['year']=release.year;
         label['releases'][index]['title']=release.title;
         label['releases'][index]['tracklist']=getTracklist(release.id);

       });
       //console.log(pretty(label));
       callback ? callback(label) : null;
   });
 }

Это функция, которую я использую для создания треклиста

 function getTracklist(releaseId) {
   var tracklist = [];

   var db = new Discogs().database();
   db.getRelease(releaseId, function(err, data){

       //console.log(JSON.stringify(data, null, 2));
        console.log('get tracklist for '+releaseId)

       discogsTracklist = data.tracklist;

       discogsTracklist.forEach(function(track, index) {
         //console.log(track.title);
         tracklist[index] = {};
         tracklist[index].order = index+1;
         tracklist[index].position = track.position;
         tracklist[index].title = track.title;

         var artists = [];
         track.artists && track.artists.forEach(function(artist, index) {
           artists[index] = artist.name;
         })
         tracklist[index].artists = artists.join(" & ");

       })

       //console.log(tracklist);
       return tracklist;
   });

 }

Я попытался заполнить треклист обратным вызовом, но он все еще выполняется в конце. Где я должен разместить обратный звонок?

Уловка в том, что мне нужен параметр index для определения позиции в массиве релизов.

   41 function getLabelReleases(label, callback) {
   42   label['releases'] = [];
   43   
   44   var db = new Discogs().database();
   45   db.getLabelReleases(label.id, function(err, data){
   46       //console.log(JSON.stringify(data, null, 2));
   47       
   48       data.releases.forEach(function(release, index) {
   49         //console.log(pretty(release));
   50         label['releases'][index]= {};
   51         
   52         label['releases'][index]['order']=index+1;
   53         label['releases'][index]['id']=release.id;
   54         label['releases'][index]['catno']=release.catno;
   55         label['releases'][index]['year']=release.year;
   56         label['releases'][index]['title']=release.title;
~  57         
+  58         getTracklist(release.id, function (tracklist) {
+  59           label['releases'][index]['tracklist']=tracklist;
+  60         });
+  61 
   62          
   63       });
   64       //console.log(pretty(label));
   65       if(callback) callback(label);
   66   });
   67 }

и добавлен обратный вызов:

   70 // TRACKLIST
   71 
~  72 function getTracklist(releaseId, callback) {
   73   var tracklist = [];
   74 
   75   var db = new Discogs().database();
   76   db.getRelease(releaseId, function(err, data){
   77 
   78       //console.log(JSON.stringify(data, null, 2));
   79        console.log('get tracklist for '+releaseId)
   80 
   81       discogsTracklist = data.tracklist;
   82 
   83       discogsTracklist.forEach(function(track, index) {
   84         //console.log(track.title);
   85         tracklist[index] = {};
   86         tracklist[index].order = index+1;
   87         tracklist[index].position = track.position;
   88         tracklist[index].title = track.title;
   89 
   90         var artists = [];
   91         track.artists && track.artists.forEach(function(artist, index) {
   92           artists[index] = artist.name;
   93         })
   94         tracklist[index].artists = artists.join(" & ");
   95 
   96       })
   97 
   98       //console.log(tracklist);
~  99       if(callback) callback(tracklist);
  100   });

Ответы [ 2 ]

0 голосов
/ 08 января 2019

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

  46 function getLabelReleases(label, callback) {
   47   label['releases'] = [];
   48 
   49   var db = new Discogs().database();
   50   db.getLabelReleases(label.id, function(err, data){
   51       //console.log(JSON.stringify(data, null, 2));
   52 
   53       data.releases.forEach(function(release, index) {
   54         //console.log(pretty(release));
~  55 
~  56         getTracklist(release.id, function (tracklist) {
~  57           label['releases'][index]= {};
~  58 
~  59           label['releases'][index]['order']=index+1;
~  60           label['releases'][index]['id']=release.id;
~  61           label['releases'][index]['catno']=release.catno;
~  62           label['releases'][index]['year']=release.year;
+  63           label['releases'][index]['title']=release.title;
+  64           label['releases'][index]['tracklist']=tracklist;
+  65 
+  66           if(callback) callback(label);
+  67         });
+  68 
   69 
_  70       });
   71   });
0 голосов
/ 08 января 2019

Если по какой-то причине вы не можете использовать Promises или async / await, взгляните на эту библиотеку: https://github.com/caolan/async

Теперь, чтобы найти решение для обещания, сначала нужно обещать функцию getTracklist:

function getTracklist(releaseId) {
    var tracklist = [];
    var db = new Discogs().database();
    return new Promise((resolve, reject) => {
        db.getRelease(releaseId, function (err, data) {
            if (err) {
                return reject(err);
            }
            //console.log(JSON.stringify(data, null, 2));
            console.log('get tracklist for ' + releaseId)
            discogsTracklist = data.tracklist;
            discogsTracklist.forEach(function (track, index) {
                //console.log(track.title);
                tracklist[index] = {};
                tracklist[index].order = index + 1;
                tracklist[index].position = track.position;
                tracklist[index].title = track.title;
                var artists = [];
                track.artists && track.artists.forEach(function (artist, index) {
                    artists[index] = artist.name;
                })
                tracklist[index].artists = artists.join(" & ");
            })
            //console.log(tracklist);
            resolve(tracklist);
        });
    });

}

Тогда вместо forEach вы можете map дорожки для Promises и ждать, пока все они закончат, используя Promise.all:

function getLabelReleases(label, callback) {
    label['releases'] = [];

    var db = new Discogs().database();
    db.getLabelReleases(label.id, function (err, data) {
        //console.log(JSON.stringify(data, null, 2));

        Promise.all(data.releases.map(function (release, index) {
            //console.log(pretty(release));
            label['releases'][index] = {};

            label['releases'][index]['order'] = index + 1;
            label['releases'][index]['id'] = release.id;
            label['releases'][index]['catno'] = release.catno;
            label['releases'][index]['year'] = release.year;
            label['releases'][index]['title'] = release.title;

            return getTracklist(release.id).then((tracklist) => {
                label['releases'][index]['tracklist'] = tracklist;
                return tracklist;
            });


        })).then(() => {
            //console.log(pretty(label));
            if (callback) callback(label);
        });
    })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...