-1

I am trying to populate Array asynchronously with data captured from MongoDB. I have a set of functions, which should execute one by one to merge 2 results from different tables into one, but upon execution, error is porduced:

TypeError: Cannot read property 'apply' of undefined

Here is a code of the router:

var Co2 = require("./../models/co2.model"),
  Dht = require("./../models/co2.model"),
  express = require("express"),
  q = require("q"),
  router = express.Router();

router.get("/all", function(req, res, next) {
  var co2Collector = function() {
    Co2.showAll(function(err, results) {
      co2Data = [];
      if (err) {
        res.json(err);
      }
      for (i = 0; i < results.length; i++) {
        co2Data.push(results[i]);
      }
      return co2Data;
    });
  };

  var dhtCollector = function() {
    Dht.showAll(function(err, results) {
      dhtData = [];
      if (err) {
        res.json(err);
      }
      for (i = 0; i < results.length; i++) {
        dhtData.push(results[i]);
      }
      return dhtData;
    });
  };

  var dataMerge = function(co2Data, dhtData) {
    mergedData = [];

    mergedData = mergedData.concat(co2Data, dhtData);
    res.json({
      message: "Done!",
      result: mergedData
    });
  };

  q
    .fcall(co2Collector())
    .then(dhtCollector())
    .then(dataMerge())
    .done();
});

module.exports = router;

The logic seems to be correct to me, but, then again, I am new to this kind of stuff and documentation is a little bit vague for my understanding. Thanks for the help!

P.S: Can the issue be in the Schema and static method? In return, no matter what adjustments are made to the code, result is either undefined, either null.

Here is my mongoose schema:

var CO2Schema = mongoose.Schema(
    {
    location:{ type: String,required: true },
    reading: { type: String, required: true }
    },
    {
    timestamps: { createdAt : 'created_at', updatedAt : 'updated_at' },
    }
);

// Get CO2 results
CO2Schema.statics.showAll = function(cb) {
    return this.find({}, cb);
};
Marks Gniteckis
  • 473
  • 1
  • 6
  • 18

2 Answers2

0

Here you are calling all three functions upfront, and waiting on the responses

q
  .fcall(co2Collector())
  .then(dhtCollector())
  .then(dataMerge())
  .done();

is effectively:

var a = co2Collector();
var b = dhtCollector();
var c = dataMerge();

q
  .fcall(a)
  .then(b)
  .then(c)
  .done();

You should either pass in the function itself as the argument, or an arrow function.

q
  .fcall(co2Collector)

or

q
  .fcall(() => co2Collector())

etc.

Buh Buh
  • 7,443
  • 1
  • 34
  • 61
  • OK, that resolves the logical issue. But now, instead of array as JSON response, I get `{ "message": "Done!", "result": [ null, null ]}` – Marks Gniteckis Feb 18 '18 at 18:59
0

If this is a func returning promise then you need to return it. Co2.showAll from co2Collector so that q can pass the value to the next chaining function. Need to call .all([co2Collector(), dhtCollector()]) so that both the values are passed to dataMerge

q.fcall(dhtCollector) is needed to convert the function to a promise

var Co2 = require("./../models/co2.model"),
  Dht = require("./../models/co2.model"),
  express = require("express"),
  q = require("q"),
  router = express.Router();

router.get("/all", function(req, res, next) {
  var co2Collector = function() {
    return Co2.showAll(function(err, results) {
      co2Data = [];
      if (err) {
        res.json(err);
      }
      for (i = 0; i < results.length; i++) {
        co2Data.push(results[i]);
      }
      return co2Data;
    });
  };

  var dhtCollector = function() {
    return Dht.showAll(function(err, results) {
      dhtData = [];
      if (err) {
        res.json(err);
      }
      for (i = 0; i < results.length; i++) {
        dhtData.push(results[i]);
      }
      return dhtData;
    });
  };

  var dataMerge = function(results) {
    co2Data = results[0].value;
    dhtData = results[1].value;
    mergedData = [];

    mergedData = mergedData.concat(co2Data, dhtData);
    res.json({
      message: "Done!",
      result: mergedData
    });
    return mergedData;
  };

  q
    .all([q.fcall(co2Collector), q.fcall(dhtCollector)])
    .then(dataMerge)
    .done();
});

module.exports = router;
Sidtharthan
  • 197
  • 9
  • Seems like `co2Data = results[0].value;` is undefined. I don't get it, since when I `console.log()` it, it returns a JSON file. – Marks Gniteckis Feb 18 '18 at 19:08
  • 1
    I think this is what needed `q.all([q.fcall(co2Collector), q.fcall(dhtCollector)])` – Sidtharthan Feb 18 '18 at 19:10
  • After hour of poking around, I still cant get it to work. When accessing API on that route, I get `{ "message": "Done!", "result": [ null, null ] }` and I have made some minor changes to code as well. `dhtCollector` is catching `co2Collector`'s result for no reason as well. – Marks Gniteckis Feb 18 '18 at 20:24