gpt4 book ai didi

node.js - fs.promises.readFile 中没有堆栈 ENOENT 错误

转载 作者:行者123 更新时间:2023-12-04 17:18:05 24 4
gpt4 key购买 nike

const fs = require('fs');

async function read() {
return fs.promises.readFile('non-exist');
}

read()
.then(() => console.log('done'))
.catch(err => {
console.log(err);
})
给出:
➜  d2e2027b node app.js
[Error: ENOENT: no such file or directory, open 'non-exist'] {
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: 'non-exist'
}
➜ d2e2027b
堆栈丢失。如果我使用 fs.readFileSync相反,它按预期显示堆栈。
➜  d2e2027b node app.js
Error: ENOENT: no such file or directory, open 'non-exist'
at Object.openSync (node:fs:582:3)
at Object.readFileSync (node:fs:450:35)
at read (/private/tmp/d2e2027b/app.js:4:13)
at Object.<anonymous> (/private/tmp/d2e2027b/app.js:8:1)
作为一个 super 丑陋的解决方法,我可以放置 try/catch 并在 ENOENT 的情况下抛出一个新错误,但我确信那里有更好的解决方案。
read()
.then(() => console.log('done'))
.catch(err => {
if (err.code === 'ENOENT') throw new Error(`ENOENT: no such file or directory, open '${err.path}'`);
console.log(err);
})
(我尝试了 Node v12、v14、v16 - 相同)

最佳答案

Nodejs 有几个模块会抛出无用的错误 stack特性;在我看来,这是一个错误,但它自 nodejs 一开始就存在,由于担心向后兼容性,此时可能无法更改(编辑:我收回这个;stack 属性是非标准的,开发人员应该知道不要依赖它的结构;nodejs 真的应该做出改变以抛出更有意义的错误)。
我已经包装了我在 nodejs 中使用的所有此类函数,修改它们以抛出正确的错误。可以使用此函数创建此类包装器:

let formatErr = (err, stack) => {
// The new stack is the original Error's message, followed by
// all the stacktrace lines (Omit the first line in the stack,
// which will simply be "Error")
err.stack = [ err.message, ...stack.split('\n').slice(1) ].join('\n');
return err;
};
let traceableErrs = fnWithUntraceableErrs => {

return function(...args) {

let stack = (new Error('')).stack;
try {

let result = fnWithUntraceableErrs(...args);

// Handle Promises that resolve to bad Errors
let isCatchable = true
&& result != null // Intentional loose comparison
&& result.catch != null // Intentional loose comparison
&& (result.catch instanceof Function);
return isCatchable
? result.catch(err => { throw formatErr(err, stack); })
: result;

} catch(err) {

// Handle synchronously thrown bad Errors
throw formatErr(err, stack);

}

};

}
这个包装器处理简单的函数、返回 promise 的函数和异步函数。基本前提是在调用包装函数时初始生成一个栈;此堆栈将具有导致调用包装函数的调用者链。现在,如果抛出错误(同步或异步),我们会捕获错误,设置其 stack属性变为有用的值,并再次抛出;如果您愿意,可以“捕获并释放”。
这是我使用这种方法在终端中看到的:
> let readFile = traceableErrs(require('fs').promises.readFile);
> (async () => await readFile('C:/nonexistent.txt'))().catch(console.log);
Promise { <pending> }
> ENOENT: no such file or directory, open 'C:\nonexistent.txt'
at repl:5:18
at repl:1:20
at repl:1:48
at Script.runInThisContext (vm.js:120:20)
at REPLServer.defaultEval (repl.js:433:29)
at bound (domain.js:426:14)
at REPLServer.runBound [as eval] (domain.js:439:12)
at REPLServer.onLine (repl.js:760:10)
at REPLServer.emit (events.js:327:22)
at REPLServer.EventEmitter.emit (domain.js:482:12) {
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'C:\\nonexistent.txt'
}
如果要整改 fs.promises套件抛出好的错误,你可以这样做:
let fs = { ...require('fs').promises };
for (let k in fs) fs[k] = traceableErrs(fs[k]);

(async () => {
// Now all `fs` functions throw stackful errors
await fs.readFile(...);
await fs.writeFile(...);
})();

关于node.js - fs.promises.readFile 中没有堆栈 ENOENT 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68022123/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com