如果您能帮助我理解猫鼬生成的错误,我将不胜感激。
日志错误:
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()) })
注意,如果您只想键(而不是值(不区分大小写,我们建议使用自定义解析器,只将键转换为小写。
感谢大家的回答!