【问题标题】:sails.js node.js Parse JSON on controllersails.js node.js 在控制器上解析 JSON
【发布时间】:2017-11-20 20:43:42
【问题描述】:

在我的名为 MapController 的控制器中,我正在执行一个函数来解析远程 json 文件,并从 if-else 结构中在名为“parsewebservice”的数组中添加一些值,显然一切正常,但 console.log (解析网络服务);没有在它返回空的地方返回传递给数组“parsewebservice”的值。但是当我把它放在 forEach 里面时,它会返回,但是一切都杂乱无章并重复,这不是正确的方法。

我想知道为什么传递给数组“parsewebservice”的值在 populada 之后没有与变量一起出现,正确的方法是什么?

下面是我的代码:

/**
 * 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);

    });

  },

};

【问题讨论】:

  • req(url, function(err, res, retorno) { 的执行是异步的,你的代码在请求完成之前就到达了console.log(parsewebservice),这就是为什么它是空的......你可以访问异步结果值的唯一地方是里面它的回调函数
  • 谢谢@Amr Labib 你有这个案例的回调函数的例子吗?

标签: javascript node.js express sails.js


【解决方案1】:

我的第一条评论必须是您不应该将function(req, res)var req = require('request') 结合使用...您将失去对原始req 对象的访问权限!

因此,您需要运行一系列异步任务,并在它们全部完成后执行一些操作。这绝不是一件容易的事,无论如何,您都必须习惯这样的想法,即您的代码不会在您编写时从上到下运行。您在底部的console.log 在您传递给外部请求的任何回调(您传入的函数)之前运行。

正确的做法是使用 Promise。看起来您正在使用this 请求库,其返回的请求只能接受回调,不能作为承诺返回。您可以为它们创建自己的 Promise 包装器,或使用替代库(有几个是 recommended on the page)。


我不想在这里写一个完整的 Promise 简介,所以我要做的是给你一个不那么漂亮但也许更容易理解的方式来在你所有的请求完成时运行一些代码。

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
});    

【讨论】:

  • 我创建了一个回调函数,但 forEach 仍然没有返回值“parsewebservice”。
  • 我无法在没有看到代码的情况下进行诊断 - 它看起来像我在答案中提供的吗?您是否使用console.log 来确保代码正在运行?
【解决方案2】:

我解决了这个问题。

“请求”模块是异步的,所以我们需要等待它响应,然后将响应发送到视图。

为此,我们创建了一个名为“foo”的函数来包含 foreach 和请求,我们对该函数进行了回调,最后我们在该函数中做出了响应(res.view),以便控制器响应仅在“foo”函数对回调的响应之后发送。因此,我们能够使用 foreach 和“request”模块解析“data”集合中的数据并将对象发送到视图。

非常感谢所有帮助过我的人,我真诚的感谢。

【讨论】:

    猜你喜欢
    • 2013-11-22
    • 2013-02-04
    • 1970-01-01
    • 2017-04-06
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    相关资源
    最近更新 更多