【发布时间】:2018-08-28 17:04:58
【问题描述】:
我有这个简单的快速代码:
const api = Router()
api.post('/some-point', async (req, res, next) => {
const someStuffToSend = await Promise.resolve("hello");
res.json({ someStuffToSend });
})
它在我的开发环境中运行良好,但在 prod 上我收到以下错误:
TypeError: argument entity must be string, Buffer, or fs.Stats
at etag (/[...]/node_modules/etag/index.js:83:11)
at generateETag ([...]/node_modules/express/lib/utils.js:280:12)
at ServerResponse.send ([...]/node_modules/express/lib/response.js:200:17)
at ServerResponse.json ([...]/node_modules/express/lib/response.js:267:15)
at api.post (/the/code/above)
我在node_modules/etag/index.js:83:11查看并看到了
if (!isStats && typeof entity !== 'string' && !Buffer.isBuffer(entity)) {
throw new TypeError('argument entity must be string, Buffer, or fs.Stats')
}
在这段代码之前我添加了一个 printf 来检查实体的类型:
console.log("Entity contains", entity, "is of type", typeof entity, "with constructor", entity.constructor, "and is it a buffer?", Buffer.isBuffer(entity))
这让我得到了下面的输出:
Entity contains <Buffer 7b 22 70 72 65 64 69 63 74 69 6f 6e 5f 69 64 22 3a 22 63 4b 57 41 64 41 46 43 77 6e 55 43 22 2c 22 69 6e 69 74 69 61 6c 5f 70 72 65 64 69 63 74 69 6f ... > is of type object with constructor function Buffer(arg, encodingOrOffset, length) {
if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
return new Buffer(arg, encodingOrOffset, length)
}
// Common case.
if (typeof arg === 'number') {
if (typeof encodingOrOffset === 'string') {
throw new Error(
'If encoding is specified then the first argument must be a string'
)
}
return allocUnsafe(this, arg)
}
return from(this, arg, encodingOrOffset, length)
} and is it a buffer? false
所以看起来实体是一个缓冲区,但不被识别。如果我将测试注释掉,它会在不同的位置崩溃
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string or Buffer
at ServerResponse.end (_http_outgoing.js:747:13)
at ServerResponse.send ([...]/node_modules/express/lib/response.js:221:10)
at ServerResponse.json ([...]/node_modules/express/lib/response.js:267:15)
at api.post (/the/code/above)
如果您查看/node_modules/express/lib/response.js:221:10,您会看到
this.end(chunk, encoding);
编码来自上面几行(l. 189,我用 printf 检查)
chunk = Buffer.from(chunk, encoding)
我可以破解 lib 以使其工作,但我怀疑一些损坏的 node_modules 文件夹。但是,即使在 rm package-lock.json; rm -rf node_modules; npm i 之后,错误仍然存在。
任何有关如何解决此问题的线索将不胜感激。
以下是我的版本号:
- 节点 9.8.0(也尝试使用 8.4.0),使用 nvm 在本地安装
- npm 5.6.0
- 表达 4.16.3
- ts-node 5.0.1
- 打字稿 2.7.2
编辑 1
- 用更简单的方法替换异步调用
- 指定快速版本
编辑 2
我删除了 node_modules 文件夹,然后 npm i 一个一个的包:
npm i aws-sdk body-parser bunyan check-types deepcopy duck-type express fast-csv glob handlebars http-auth md5 moment moment-timezone multer node-stream object-path randomstring
仍然得到同样的错误。
编辑 3
添加有关环境的更多信息。
编辑 4
好的,想通了。这是一个与 ts-node 配置相关的问题。 我正在启动我的服务器
ts-node --harmony_async_iteration -r tsconfig-paths/register ./src/index.ts
在我的tsconfig.json 中有以下几行:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"lib": [ "es2017", "esnext.asynciterable" ],
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"pretty": true,
"paths": {
"*": [
"*", "src/*", "src/types/*",
"node_modules/*"
]
}
},
"include": [ "src/**/*" ]
}
由于命令行中有-r tsconfig-paths/register,所以加载了tsconfig.json中指定的路径,包括paths['*']中的"node_modules/*"。
我不知道为什么,但看起来这会导致 node_modules 中的库被加载两次,从而破坏了基于构造函数(例如 instanceof)的类型检查。
问题
我不确定完全理解其中的原因。有灯吗?
【问题讨论】:
-
someAsyncFunc()究竟解析了什么?你能给我们看一下代码吗? -
另外,您在生产中运行的是什么版本的 Express?
-
感谢您的关注。我用
Promise.resolve()替换了异步调用,但它仍然因同样的错误而崩溃。我也是 Express 版本(产品和开发版本均为 4.16.3) -
我会明确建议所有依赖模块并从 NPM 干净地重新加载它们。
-
我来一一安装吧……
标签: node.js typescript express npm