嵌套异步功能

时间:2019-01-08 19:14:16

标签: javascript node.js asynchronous

我正在创建一个脚本来收集来自Discog的每个发行版的跟踪列表。 我的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 :(得分:0)

如果由于某种原因您不能使用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);
        });
    })
}

答案 1 :(得分:0)

我通过使用以下回调修复了该问题。将对承诺进行调查,看看是否有更好的方法。

public class Blah {

    public void whatever() {
        ScheduledExecutorService scheduledExecutorService =
            Executors.newScheduledThreadPool(5);
        IntStream.range(0, 4).forEach(i -> {
            scheduledExecutorService.scheduleWithFixedDelay(runOnce(i),
                0, 5000, TimeUnit.MILLISECONDS);
        });
    }

    private Runnable runOnce(int i) {
        return () -> System.out.println(i);
    }
}