JSON响应上的重复块

Posted

技术标签:

【中文标题】JSON响应上的重复块【英文标题】:Duplicate chunks on JSON response 【发布时间】:2014-09-10 05:55:03 【问题描述】:

我有一个相当标准的 MEAN 项目设置,使用 yeoman 使用 angular-fullstack 生成器。

我发现,当获取较大(超过 65536 字节)的 json 结果时,它使用 gzip 进行编码并分块,但返回的 json 在 chrome 中查看或由我的角度客户端 $resource 使用时无效,因为它包含两个响应! 例如 name:'hi'name:'hi' 用于单个 id 或 [..,..][..,..] 用于数组。

服务器 api 端点是从 angular-fullstack 生成器自动生成的,看起来像:

// Get list of worlds
exports.index = function(req, res) 
  World.find(function (err, worlds) 
    if(err)  return handleError(res, err); 
    res.json(200, worlds);
  );
;

如果我对数据进行切片使其不分块,则 json 格式良好。我检查了 mongo db,那里的数据也正常,调试 worlds 变量,我可以 JSON.stringify 并获得预期的字符串结果而没有任何重复。但是在它发送的那一刻,我在响应中得到了两倍的 json 结果。

更新评论

角全栈 2.0.4

架构如下:

'use strict';

var mongoose = require('mongoose'),
    Schema = mongoose.Schema;

var WorldSchema = new Schema(
  name: String,
  info: String,
  active: Boolean,
  tiles: [Schema.Types.Mixed]
);

module.exports = mongoose.model('World', WorldSchema);

播种:

 var newWorld = new WorldModel(
                    _id: planet._objectId,
                    name: "SimDD World",
                    tiles : seed()
                );
                newWorld.save();

...

var seed = function () 
    var data = [];
    for (var i = 0; i < planet.HEIGHT; i++) 
        for (var j = 0; j < planet.WIDTH; j++) 
            data.push(
                coords:
                    x:i,
                    y:j
                ,
                type:'.'
            );
        
    
    return data;

【问题讨论】:

你用的是什么版本的af?你能发布一个模型和种子数据吗? @AndyGaskell 更新了问题,虽然我不认为数据本身是问题,因为只要没有分块,我就可以用较小的数据集恢复预期的结构 会不会和Mongo的GridFS有关? @Goodzilla 有趣的阅读,但我不这么认为......首先,我必须使用cursor = db.fs.chunks.find(files_id: myFileID).sort(n:1); fs 相关命令来做我的发现,对吗?脚手架的服务器控制器似乎根本没有这样做。其次,响应仅达到 120k gzipped,远不及 16megs 但超过 65k。 您使用的是什么浏览器(和版本),您是否尝试将其复制到其他浏览器? 【参考方案1】:

看起来这是由压缩中间件引起的,从 express 配置中删除 app.use(compression()); 似乎可以解决此问题。

【讨论】:

嘿! DaftMonk :) 感谢 angular fullstack 生成器,仅通过查看您如何构建服务器/客户端控制器、套接字、模型等,我就学到了很多最佳实践。 是你的答案,是的,它确实解决了它,但它增加了 10 倍的传输大小,并不理想,但是嘿,我不是一个贪婪的人,这已经足够好了。听起来好像不是根本原因? 如果您使用yo-angular-fullstack(PS 感谢您的出色工作!)或connect-livereload 模块将connect-livereload 升级到更新版本&gt;= 0.4.1,则解决此问题。 issue here中的 cmets 【参考方案2】:

问题出现在浏览器中,而不是在邮递员中。我检查了 HTTP 请求标头,当我在邮递员中将“接受”标头添加为 html 时,邮递员中也会出现同样的问题。所以我相信浏览器对 Accept 类型和 html 的处理方式不同。

【讨论】:

【参考方案3】:
// app.use(require('connect-livereload')());

我在构建 angular-fullstack 应用程序时遇到了同样的问题(感谢 DaftMonk),在使用节点检查器进行了一些广泛的调试后,结果 JSON 数据被传递到 livereload 模块并在它到来时被复制出去。禁用这个中间件为我解决了这个问题。

【讨论】:

【参考方案4】:

这对你有用吗?我看不出它不应该这样做的原因。 我假设您的行星对象具有:HEIGHTWIDTH_objectId 属性。

记住如果你修改了一个混合类型你需要告诉猫鼬 该值已更改并随后保存。http://mongoosejs.com/docs/schematypes.html#mixed

var WorldModel = require('../api/world/world.model');
var planet = require('planetSeedData');

var seed = function() 
  var data = [];
  for (var i = 0; i < planet.HEIGHT; i++) 
    for (var j = 0; j < planet.WIDTH; j++) 
      data.push(
        coords: x:i, y:j,
        type: '.'
      );
    
  
  return data;
;

var myPlanet = 
  _id: Mongoose.Types.ObjectId(planet._objectId),
  name: "SimDD World",
  tiles : seed()
;               

WorldModel.create(myPlanet);

// if modified, you would do something like:
// WorldModel.markModified('tiles');
// WorldModel.save();

【讨论】:

答案的方向有点不舒服,因为正如问题中所述,我对 mongoose、创建/保存数据到 mongodb 或在我的节点控制器中获取数据没有任何问题。只有当我将该数据发送到客户端时,响应才会认为复制块是明智的。我看不出这与我存储/更新数据的方式或这将如何影响响​​应有何不同。即使我这样做了:res.json(200, JSON.stringify(worlds)); 我仍然遇到问题。这只是发回一个字符串,与猫鼬没有关系了。 哇,这真的很奇怪。复制您的结果后,我会看看是否可以改进我的答案 我无法复制,错误在其他地方,我认为它不在数据库中,但更有可能在压缩方法中。你能用最少的代码做一个要点吗?另一方面,我认为你可以用这个来修补它:var json = JSON.stringify(worlds); res.json(200, json.substr(0, json.length / 2)); 这很丑,但它应该可以工作。 hum... 世界数组正在扩展,但是当它超过固定大小 (65k) 时就会开始压缩。将其除以 2 不会减少它。

以上是关于JSON响应上的重复块的主要内容,如果未能解决你的问题,请参考以下文章

响应式网格图块覆盖[重复]

在 AFNetworking 2 的失败块中访问 JSON 响应

检查 JSON 响应数据是不是为空 [重复]

JSON 响应中的重复字段

localhost上的测试Laravel API无法获得响应

使用AngularJS中的重复键迭代json响应[重复]