zoukankan      html  css  js  c++  java
  • 解决Mongoose 返回的文档过大导致模板引擎art-template无法渲染的问题,错误-RangeError: Maximum call stack size exceeded

    参考:https://blog.csdn.net/qq_40659195/article/details/88411838

    最近尝试用Node写一个小案例,使用到了MongoDB,使用过的人可以知道,Node-js操作MongoDB的官方包实在有些麻烦,为了方便开发,使用了mongoose这样的一个中间插件,但是却发现,查询的数据无法通过art-template渲染(注: 这里使用的express框架,通过express配置的art-template),结果报错:

    Maximum call stack size exceeded
    at Buffer.get [Symbol.toStringTag] ()
    at Buffer.toString ()

    根据问题描述,应该是内存问题,按照我的性格,当然先百度一下(有谷歌的通知勿喷,最近翻墙老是出问题),大多数写的都是递归造成的问题描述,我靠,这和我情况一毛钱关系没有,故转而还是自己想办法,经过一番折腾,发现,只有mongoose返回的文档对才会导致该问题,如果自己定义的JSON数据或者对象的数据都没有这样的情况,果断得出结果------是mongoose返回文档对象太过庞大造成,然后又折腾了一番,toString,对象拷贝,都没有成功,因为文档对象是不可变的(这句话现在是有些正确的,尽管还没有绝对的证据)!最后按照JSON格式数据操作一番,

    先通过JSON.stringify()这个方法将文档对象转为字符串,将他的其他属性全部格式掉,只需要留下需要的数据字符串即可!

    然后再通过JSON.parse()这个方法转为对象,这个方法虽然丢失效率,但是暂时解决问题,后面有更好的解决方案或者楼主得到了原因会更新解决方法和方案!代码附上,希望了解该问题的大神能提点一二!

    评论区解决方案引申:

    可以在查询链上使用lean()。告诉mongoose返回普通对象 不返回mongoose文档对象

    我的最终解决方案:

    // 解决方案1:
    // 使用lean()
    // let result = await Article.find({}).populate('author').lean();
    
    // 解决方案2:
    // 如果使用了第三方模块mongoose-sex-page控制查询数据,则不能使用lean()。
    // 导入第三方模块mongoose-sex-page控制分页查询的数据
    const pagination = require('mongoose-sex-page');
    let result = await pagination(Article).page(1).size(4).display(5).find({}).populate('author').exec();
    
    result = JSON.stringify(result);
    result = JSON.parse(result); 
    

    知识扩展:

    参考:Mongoose - lean
    Faster Mongoose Queries With Lean

    默认情况下,Mongoose查询返回Mongoose Document类的实例。 文档比普通的JavaScript对象重得多,因为它们具有很多用于跟踪更改的内部状态。 启用lean选项会告诉Mongoose跳过实例化完整的Mongoose文档,只给您POJO。

    lean属性的作用:跳过转换为MongooseDocuments类型,直接返回JS Object,从而便于我们修改查询结果。

    mongoose查询:

    • Model.findOne({});
    • Model.save();

    以上2种查询返回的数据实际上是Mo

    ngooseDocuments对象(mongoose自己封装的一个对象),并且这个对象会对数据进行实时查询以保证其符合预定义的model。所以添加其它model中没有的属性时是无法添加成功的。

    要想添加成功有2种方法:

    1. 查询时添加lean,
    • Model.findOne({}).lean();
    • Model.findOne({lean:true},function(err,result){});
    • Model.findOne({}).lean().exec(function(err,result){});
    1. 将查询结果转为object,查询结果result.toObject();
  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/jeacy/p/13560379.html
Copyright © 2011-2022 走看看