Nodejs 重复拒绝(未处理的并且在 try/catch 块中)
Nodejs duplicate rejection (unhandled one and in a try/catch block)
通过使用 node js 12.16.1 LTS
我不明白为什么这段代码会导致 双重拒绝(一个未处理,一个被捕获)。
当我 删除 p promise 并等待 create_bug() 中的 p 时,它运行良好(只有一个拒绝在 try catch 块中捕获)。我不知道为什么。
Nodejs 专家,你能帮忙吗?
'use strict';
process.on('uncaughtException', (err) => {
console.error(`uncaughtException: ${JSON.stringify({name: err.name, msg: err.message})}`);
});
process.on('unhandledRejection', (err) => {
console.error(`unhandledRejection: ${JSON.stringify({name: err.name, msg: err.message})}`);
});
async function create_bug() {
console.log('In create');
let res = superCreate();
console.log(`In create, res = ${res}`);
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
return res;
}
async function superCreate() {
console.log('superCreate : now throwing');
throw new Error("Something wrong");
}
async function create_OK() {
console.log('In create');
let res = await superCreate();
console.log(`In create, res = ${res}`);
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
return res;
}
async function main() {
try {
let res = await create_bug();
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
}
main().then(() => {
setTimeout(() => console.log(`Finished`), 2000);
});
来自您的 superCreate
的变量 res
中包含的承诺 未等待 并且 未附加 在它被拒绝之前给它一个 catch
处理程序。因此未处理的承诺拒绝被触发。当在 main
.
中触发等待时,拒绝后会附加一个处理程序
请注意,拒绝处理程序即使在被拒绝后附加到承诺上也会被调用。尝试例如:
async function main() {
let res = create_bug();
try {
await res;
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
res.catch(err => console.error(`main1: ${JSON.stringify({name: err.name, msg: err.message})}`));
res.catch(err => console.error(`main2: ${JSON.stringify({name: err.name, msg: err.message})}`));
}
请注意,您现在还会收到 "main1" 和 "main2" 错误。
或者,尝试从 superCreate
函数中删除 async
,现在您应该会看到 In create, res = ${res}
没有打印出来,而是同步处理异常。
另一种选择是直接从 create_bug
return res 而不等待 main
中的 res
。然后您将看到与原始行为类似的行为:未处理的拒绝和 "normal" 捕获处理块。
async function create_bug() {
console.log('In create');
let res = superCreate();
console.log(`In create, res = ${res}`);
return res;
}
async function superCreate() {
console.log('superCreate : now throwing');
throw new Error("Something wrong");
}
async function main() {
try {
let res = create_bug();
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
await res;
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
}
通过使用 node js 12.16.1 LTS 我不明白为什么这段代码会导致 双重拒绝(一个未处理,一个被捕获)。 当我 删除 p promise 并等待 create_bug() 中的 p 时,它运行良好(只有一个拒绝在 try catch 块中捕获)。我不知道为什么。
Nodejs 专家,你能帮忙吗?
'use strict';
process.on('uncaughtException', (err) => {
console.error(`uncaughtException: ${JSON.stringify({name: err.name, msg: err.message})}`);
});
process.on('unhandledRejection', (err) => {
console.error(`unhandledRejection: ${JSON.stringify({name: err.name, msg: err.message})}`);
});
async function create_bug() {
console.log('In create');
let res = superCreate();
console.log(`In create, res = ${res}`);
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
return res;
}
async function superCreate() {
console.log('superCreate : now throwing');
throw new Error("Something wrong");
}
async function create_OK() {
console.log('In create');
let res = await superCreate();
console.log(`In create, res = ${res}`);
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
return res;
}
async function main() {
try {
let res = await create_bug();
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
}
main().then(() => {
setTimeout(() => console.log(`Finished`), 2000);
});
来自您的 superCreate
的变量 res
中包含的承诺 未等待 并且 未附加 在它被拒绝之前给它一个 catch
处理程序。因此未处理的承诺拒绝被触发。当在 main
.
请注意,拒绝处理程序即使在被拒绝后附加到承诺上也会被调用。尝试例如:
async function main() {
let res = create_bug();
try {
await res;
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
res.catch(err => console.error(`main1: ${JSON.stringify({name: err.name, msg: err.message})}`));
res.catch(err => console.error(`main2: ${JSON.stringify({name: err.name, msg: err.message})}`));
}
请注意,您现在还会收到 "main1" 和 "main2" 错误。
或者,尝试从 superCreate
函数中删除 async
,现在您应该会看到 In create, res = ${res}
没有打印出来,而是同步处理异常。
另一种选择是直接从 create_bug
return res 而不等待 main
中的 res
。然后您将看到与原始行为类似的行为:未处理的拒绝和 "normal" 捕获处理块。
async function create_bug() {
console.log('In create');
let res = superCreate();
console.log(`In create, res = ${res}`);
return res;
}
async function superCreate() {
console.log('superCreate : now throwing');
throw new Error("Something wrong");
}
async function main() {
try {
let res = create_bug();
let p = new Promise((a, r) => setTimeout(() => a(), 0));
await p;
await res;
console.log(`create result : ${res}`);
} catch (err) {
console.error(`ERROR caught in main : ${JSON.stringify({name: err.name, msg: err.message})}`);
}
}