Vikum Dheemantha
Vikum Dheemantha

Reputation: 843

Strongloop Loopback - asynchronous functions handling in remote method (inside for each function)

I am developing a api using Loopback and I develop some remote method to retrieve data from efferent modules and rearrange the data as I wish. This is my sample code.

mainModule.viewAll = function(cb) {
    var mainFilter = {fields: ['f_name', 'l_name', 'id'], where: {status: 1}};
    var cEmp = null;
    mainModule.find(mainFilter, function(err, mainModules) {
      var returnArray = [];
      var returnEle;
      var secondModule = app.models.secondModule;

      mainModules.forEach(emp=>{
        returnEle = {};
        returnEle['name'] = emp.name;
          secondModule.count({ where: { type: 1 }}, function (err, count) {
              returnEle['field1'] = count;
              console.log(count);
          });
          secondModule.count({ where: { type: 1 } }, function (err, count) {
              returnEle['field2'] = count;
              console.log(count);
          });
          secondModule.count({ where: { type: 1 } }, function (err, count) {
              returnEle['field3'] = count;
              console.log(count);
          });
        returnArray.push(returnEle);

      });
      cb(null, returnArray);
    });
  };

  mainModule.remoteMethod('viewAll', {
    'http': {'verb': 'get', 'path': '/viewAll'},
    returns: {arg: 'profiles', type: 'Array'},
  });

And my response is like this,

{
  "profiles":[
    {
      "name":"Jhone",
      "id":1
    },
    {
      "name":"Shaam",
      "id":2
    },
    {
      "name":"Viki",
      "id":3
    }
    ] 
}

As you see here it only responce with the name and id fields no details about 'filed1', 'field2', 'field3'.But in console log 'field1','field2','field3' displaying perfectly.

I found that the reason could be the asynchronous behavior of the JavaScript. I study on some methods to fix this problem like using callback function, Promise etc. but none of those are fit with situation. (Promises seams little more efficient, so I tried to wrap the second module functions with the one promise and entire 'for each' function to another promise and cb(null, returnArray); was set to the then function. But it also didn't work).

I am new to the Loopback, So if someone know the answer please help me.

Upvotes: 0

Views: 781

Answers (1)

Daphoque
Daphoque

Reputation: 4678

Use async.eachOf to apply async operation on each modules, then for each modules, use async.parallel to compute your 3 count in parallel :

var returnArray = [];

async.eachOf(mainModules, function(module, index, acb){

     // for each module do parallel count

    async.parallel({

        field1: function(pcb){
            secondModule.count({ where: { type: 1 }}, pcb);
        },

        field2: function(pcb){
            secondModule.count({ where: { type: 1 } }, pcb);
        },

        field3: function(pcb){
            secondModule.count({ where: { type: 1 } }, pcb);
        }
    }, function(err, result){

        // final parallel callback, when all parallel count are finished
        if(err || !result)
        {
            return acb(err || true);
        }
        else
        {
            result.name = module.name;

            // here result contains the 3 count in result["field1"], result["field2"] and result["field3"]

            returnArray.push(result);

            return acb(null);
        }
    })


    }, function(err){
       // final async.each of callback when all modules are proceed
       if(err)
       {
          // do stg
        }
       else
      {
          return cb(null, returnArray)
      }
  })

Upvotes: 1

Related Questions