问题 JSON响应上的重复块


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

我发现的是,当获取一个较大的(超过65536字节)json结果时,它使用gzip和chunked进行编码,但返回的json无法在chrome中查看或由我的angular client $ 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数据库,数据也正常,并调试 worlds 变量,我可以JSON.stringify并获得预期的字符串结果,没有任何重复。但是当它被发送的那一刻,我正在将响应的json结果加倍。

更新 征求意见

angular-fullstack 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;
}

4175
2017-07-19 02:10


起源

您使用的是什么版本的af?你能发布模型和种子数据吗? - Andy Gaskell
@AndyGaskell更新了问题,虽然我不认为数据本身就是问题,因为只要没有分块,我就可以用较小的数据集获得预期的结构 - Joe
这不会与Mongo有关 GridFS的 ? - Goodzilla
@Goodzilla有趣的阅读,但我不这么认为......首先,我必须使用 cursor = db.fs.chunks.find({files_id: myFileID}).sort({n:1}); 用fs相关命令做我的发现吧?脚手架服务器控制器似乎根本不这样做。第二,响应仅达到120k gzipped,没有接近16megs但超过65k。 - Joe
您使用的浏览器(和版本)是什么,并且您是否尝试过在其他任何浏览器上复制它? - meeDamian


答案:


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


8
2017-07-22 04:02



嘿! DaftMonk :)感谢角度的fullstack生成器,我从了解你如何构建服务器/客户端控制器,套接字,模型等等,我学到了很多最佳实践。 - Joe
你的答案是肯定的,是的,确实可以修复它,但它会使传输大小增加10倍,不理想,但是嘿,我不是一个贪婪的家伙,这已经足够了。听起来不是根本原因吗? - Joe
如果你正在使用,修复就是这个 yo-angular-fullstack (PS感谢您的精彩工作!)或者 connect-livereload 模块是升级 connect-livereload 到更新的版本 >= 0.4.1 请参阅中的评论 问题在这里 - Julian Soro


问题出现在浏览器中而不是邮递员中。我检查了HTTP请求标头,当我在postman中添加'Accept'Header作为html时,邮递员也会看到同样的问题。所以我认为浏览器的处理方式与使用html的Accept类型不同。


1
2017-12-19 07:49





这对你有用吗?我不明白为什么不应该这样做。
我假设你有一个行星物体,它具有:
HEIGHTWIDTH 和 _objectId 属性。

请记住,如果您修改混合类型,则需要告诉mongoose 值已更改并随后保存。
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();

0
2017-07-20 08:20



答案正在进行中有点不舒服,因为如问题中所述,我没有mongoose的问题,创建/保存数据到mongodb或在我的节点控制器中取出它。只有当我将数据发送给客户端时,响应才会认为复制块是合理的。我没有看到这与我如何存储/更新数据或如何影响响​​应有多大不同。即使我这样做了: res.json(200, JSON.stringify(worlds)); 我还是遇到了问题。这只是发回一个字符串,与mongoose没有任何关系。 - Joe
哇,这真的很奇怪。我会在复制你的结果后看看能不能改进我的答案 - Josue Alexander Ibarra
我无法复制,错误在其他地方,我不认为它在数据库中,但更有可能在压缩方法中。你能用最小的代码做点什么吗?另一方面,我认为你可以用这个补丁: var json = JSON.stringify(worlds); res.json(200, json.substr(0, json.length / 2)); 这很难看,但应该有效。 - Josue Alexander Ibarra
哼......世界阵列正在扩大,但当压缩超过固定大小(65k)时压缩就会开始。将它除以2并不会削减它。 - Joe


// app.use(require('connect-livereload')());

我在构建我的angular-fullstack应用程序时遇到了同样的问题(感谢DaftMonk),在使用node-inspector进行了大量调试后,结果证明JSON数据传递给了 livereload 模块并在出现时重复。禁用此中间件可以消除我的问题。


0
2018-01-24 22:39