简体   繁体   中英

sails.js node.js Parse JSON on controller

In my controller called MapController I'm doing a function to do a parse of remote json files, and from an if-else structure add some values in an array called "parsewebservice", apparently everything is working fine but console.log ( parsewebservice); is not returning the values that were passed to the array "parsewebservice" in the place where it is returning it empty. But when I put it inside the forEach it returns, but everything cluttered and repeated then is not the right way.

I wanted to know why the values that were passed to the array "parsewebservice" are not going along with the variable after populada and what would be the correct way to do it?

Here is my code below:

/**
 * MapController
 *
 * @description :: Server-side logic for managing Maps
 * @help        :: See http://sailsjs.org/#!/documentation/concepts/Controllers
 */

module.exports = {

  index: function(req, res, next) {

    Data.find(function foundData(err, datas) {
      if (err) return next(err);

      var parsewebservice = [];

      datas.forEach(function(data, index) {

        var req = require("request");
        var url = data.address + "?f=pjson";

        req(url, function(err, res, retorno) {
          if (err) {
            console.log(err);
          } else {

            var camadas = JSON.parse(retorno);
            if (camadas.mapName) {

              camadas.layers.forEach(function(campo, i) {

                if (campo.subLayerIds != null) {


                } else if (campo.subLayerIds == null) {
                  parsewebservice.push([i, "dynamicMapLayer", campo.name, data.address]);
                }
              });

            } else if (camadas.serviceDataType) {
              parsewebservice.push([null, "imageMapLayer", camadas.name, data.address]);

            } else if (camadas.type) {
              parsewebservice.push([null, "featureLayer", camadas.name, data.address]);

            }

          }

        });

      });

      console.log(parsewebservice);

    });

  },

};

My first comment has to be that you should not combine function(req, res) with var req = require('request') ... you lose your access to the original req object!

So, you need to run a list of async tasks, and do something when they are all complete. That will never be entirely easy, and no matter what, you will have to get used to the idea that your code does not run from top to bottom as you've written it. Your console.log at the bottom runs before any of the callbacks (functions you pass in) you pass to your external requests.

The right way to do this is to use promises. It looks like you are using this request library, whose returned requests can only accept callbacks, not be returned as promises. You can create your own promise wrapper for them, or use an alternative library (several are recommended on the page ).


I don't want to write a whole intro-to-promises right here, so what I will do is give you a less pretty, but maybe more understandable way to run some code at the completion of all your requests.

Data.find(function foundData(err, datas) {
  if (err) return next(err);
  var parsewebservice = [];

  // here we will write some code that we will run once per returned data
  var processResponse = function(resp) {
      parsewebservice.push(resp);
      if(parsewebservice.length >= datas.length) {
        // we are done, that was the final request
        console.log(parsewebservice);
        return res.send({data: parsewebservice)}); // or whatever
      }
  };

  datas.forEach(function(data, index) {
    var request = require("request");
    var url = data.address + "?f=pjson";
    request(url, function(err, res, retorno) {
      // do some processing of retorno...
      // call our function to handle the result
      processResponse(retorno);
    });

  });

  console.log(parsewebservice); // still an empty array here
});    

I solved the problem.

the "request" module is asynchronous so we need to wait for it to respond and then send the response to the view.

To do this we created a function called "foo" to contain the foreach and the request, we made a callback of that function and finally we made the response (res.view) within that function, so that the controller response would only be sent after the response of the "foo" function to the callback. So we were able to parse.json the data from the "data" collection using foreach and the "request" module and send the objects to the view.

Many thanks to all who have helped me, my sincere thanks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM