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
升级到更新版本>= 0.4.1
,则解决此问题。 issue here中的 cmets 【参考方案2】:
问题出现在浏览器中,而不是在邮递员中。我检查了 HTTP 请求标头,当我在邮递员中将“接受”标头添加为 html 时,邮递员中也会出现同样的问题。所以我相信浏览器对 Accept 类型和 html 的处理方式不同。
【讨论】:
【参考方案3】:// app.use(require('connect-livereload')());
我在构建 angular-fullstack 应用程序时遇到了同样的问题(感谢 DaftMonk),在使用节点检查器进行了一些广泛的调试后,结果 JSON 数据被传递到 livereload
模块并在它到来时被复制出去。禁用这个中间件为我解决了这个问题。
【讨论】:
【参考方案4】:这对你有用吗?我看不出它不应该这样做的原因。
我假设您的行星对象具有:HEIGHT
、WIDTH
和 _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 响应