tecx20
tecx20

Reputation: 15

Loopback Async data call Nodejs

I have method which return list of shows with latest episodes release, which all return total count of episodes. I'm kind of stuck at the looping part where i need to count all episodes of show in the resulted array, as query call are async and i'm unable to syn them. It would great that can suggest solution for this problem

server.models.Eps.find({
  include:'show',
  order: 'dateadded DESC',
  limit: 10 },function (err,episodes) {
  if(err)
  { console.log(err);
    return  res.sendStatus(500);
  }
  var show = [];
  var p1 = new  Promise(function (resolve,reject) {
    for(var  i = 0; i < episodes.length;i++)
    {
      var sh = episodes[i].show();
      server.models.Eps.count({'show_id': show.id},function (err,value) {
        if(err) {
          console.log(err);
          return res.statusCode(500);
        }
        console.log(value);
        sh.episodeCounts = value;
        show.push(sh);
      });
    }
  });
  Promise.all([p1])
    .then(function (values) {
      return res.send(show);
    });
});

Upvotes: 1

Views: 1413

Answers (1)

leesio
leesio

Reputation: 741

A few things to point out here. show is defined as an empty array but then the id is referenced in the query server.models.Eps.count({'show_id': show.id},function (err,value) {. I presume that show is a key on the episode data structure so should not be a function call? Also I'm not sure why you're using Promise.all for a single promise.

I think I understand what you're trying to achieve though.

There are a couple of ways you could do this, one which requires the fewest changes and one which would probably be considered nicer.

  1. You could use the async library to iterate over the array asynchronously. It should work OK, but it's not very nice to mix callbacks and promises in such a way ( my personal view :) )

    var async = require( "async" );
    var shows = [];
    
    async.each( episodes, function( episode, cb ){
      var show = episode.show;
      server.models.Eps.count({'show_id': show.id},function(err,value) {
        if(err) {
          console.log(err);
          cb( err );
        }
        console.log(value);
        show.episodeCounts = value;
        shows.push(sh);
      },
      function( err ){
        if( err ){
          return res.statusCode(500);
        }
        else callback();
      });
    });
    
  2. The other thing you could do is wrap the server.models.Eps.count function in a wrapper that returns a promise. That way you could use a more promise-ish method of dealing with the asynchronous calls. Something like:

    server.models.Eps.find({
      include:'show',
      order: 'dateadded DESC',
      limit: 10 },function (err,episodes) {
      if(err){
        console.log(err);
        return res.sendStatus(500);
      }
      var promises = [];
      for(var  i = 0; i < episodes.length;i++)
        var show = episodes[i].show;
        promises.push( appendEpisodeCount( show ) );
      }
      Promise.all( promises )
        .then(function( shows ) {
          return res.send( shows );
        })
        .catch( function( err ){
          res.statusCode( 500 );
        });
    });
    
    function appendEpisodeCount( show )
      var promise = new Promise( function( resolve, reject ){
        var query = {
          show_id: show.id
        };
        server.models.Eps.count( query,function(err,value) {
          if( err ) return reject( err );
          show.episodeCount = value;
          resolve( show );
        });
      });
      return promise;
    }
    

Upvotes: 1

Related Questions