你能帮我找出为什么Mongoose在Object.isPOJO中返回这个未定义的错误吗



如果您能帮助我理解猫鼬生成的错误,我将不胜感激。

日志错误:

TypeError: Cannot read properties of undefined (reading 'name')
at Object.isPOJO (C:Users[...]node_modulesmongooselibutils.js:396:38)
at Object.toObject (C:[...]node_modulesmongooselibutils.js:354:15)
at model.Query.Query.find (C:[...]node_modulesmongooselibquery.js:2341:22)
at Function.find (C:[...]node_modulesmongooselibmodel.js:2244:13)
at Object.exports.findMatches (C:[...]controllersmatches.js:13:11)
at preHandlerCallback (C:[...]node_modulesfastifylibhandleRequest.js:128:37)
at preValidationCallback (C:[...]node_modulesfastifylibhandleRequest.js:112:5)
at handler (C:[...]node_modulesfastifylibhandleRequest.js:76:7)
at handleRequest (C:[...]node_modulesfastifylibhandleRequest.js:24:5)
at runPreParsing (C:[...]node_modulesfastifylibroute.js:522:5)

重点是我没有做任何与Mongoose相关的工作。我刚刚意识到,只有当我在查询中使用日期(查询示例:{startDate: { $gt: new Date(req.query.date)} }:req.query.date是ISO字符串日期(时,才会发生这种情况(突然之间,代码不久前运行良好(。现在,我在每个关于日期的查询中都会出现上述错误,而它们运行良好。

生成错误的Mongoose代码如下:

exports.isPOJO = function isPOJO(arg) {
if (arg == null || typeof arg !== 'object') {
return false;
}
const proto = Object.getPrototypeOf(arg);
// Prototype may be null if you used `Object.create(null)`
// Checking `proto`'s constructor is safe because `getPrototypeOf()`
// explicitly crosses the boundary from object data to object metadata
return !proto || proto.constructor.name === 'Object';
};

作为测试,如果我将proto.constructor.name更改为proto.constructor?.name,则可以解决错误,并且一切正常,但目标是了解发生了什么,而不是扰乱依赖代码。如果相关的话,我在这个应用程序中使用Fastify。

mongooseisPOJO代码不适用于不继承Object原型的对象。

> a = Object.create(null)
[Object: null prototype] {}
> typeof a
'object'
> a.constructor.name
Uncaught TypeError: Cannot read properties of undefined (reading 'name')

正如您提到的查询字符串,querystring.parse()返回没有Object原型的对象,因此这些默认的Object属性不会与传入的查询参数冲突。

如果你认为这种用法是有效的,也许可以在猫鼬中提出这个问题。

如果您不关心原型名称为的请求参数,则可以重建正在传递的对象

a.__proto__             a.constructor           
a.hasOwnProperty        a.isPrototypeOf
a.propertyIsEnumerable  a.toLocaleString
a.toString              a.valueOf

问题似乎与查询字符串解析有关。通过将querystringParser参数显式传递给Fastify:来解决

const querystring = require('querystring'); 
const fastify = require('fastify')({       
querystringParser: str => querystring.parse(str) 
});

注意:querystringParser通常用于更改默认解析器或更改默认行为。我不知道为什么在我看来我需要明确地设定。

关于querystringParser:的官方Fastify文档

querystringParser

Fastify使用的默认查询字符串解析器是Node.js的核心查询字符串模块。

您可以通过传递选项来更改此默认设置querystringParser,并使用自定义语法,如qs。

const qs = require('qs') 
const fastify = require('fastify')({  
querystringParser: str => qs.parse(str) 
})

你也可以使用Fastify的默认解析器,但更改了一些处理行为,如示例以下是不区分大小写的键和值:

const querystring = require('querystring') 
const fastify = require('fastify')({   
querystringParser: str => querystring.parse(str.toLowerCase()) 
})

注意,如果您只想键(而不是值(不区分大小写,我们建议使用自定义解析器,只将键转换为小写。

感谢大家的回答!

最新更新