是否可以使用承诺的ES6 .catch
语法捕获异步错误?例如,以下操作无效(.catch没有捕获错误):
new Promise((resolve, reject)=>{
setTimeout(()=>{throw new Error("uh oh")}, 1);
}).then(number=>{
console.log("Number: " + number);
}).catch(e=>{
console.log("Error: " + e);
});
但是这个同步版本确实:
new Promise((resolve, reject)=>{
throw new Error("uh oh");
}).then(number=>{
console.log("Number: " + number);
}).catch(e=>{
console.log("Error: " + e);
});
使用try / catch块并reject
捕获错误的唯一解决方案是执行以下操作吗?
new Promise((resolve, reject)=>{
try {
setTimeout(()=>{throw new Error("uh oh")}, 1);
}
catch(e) {
reject(e);
}
}).then(number=>{
console.log("Number: " + number);
}).catch(e=>{
console.log("Error: " + e);
});
为了这个问题,假设抛出错误的代码部分在另一个命名函数中,因此它无法访问reject
函数。
谢谢!
修改:Here is a more complete example of what I'd like to do, in JSFiddle.
答案 0 :(得分:2)
在resolve()
构造函数中使用reject()
,Promise
。处理onRejected
或.catch()
处的错误。
注意,一旦处理错误,应该联系onFulfilled
链接.then()
,如果有的话,除非在throw
或onRejected
中使用.catch()
,将错误明确传递给链式.then(_, onRejected)
或.catch()
function fn() {
throw new Error("uh oh")
}
new Promise((resolve, reject) => {
setTimeout(() => {
try {
resolve(fn())
} catch (e) {
reject(e)
}
}, 1);
}).then(number => {
console.log("Number: " + number);
}, e => {
console.log("Error: " + e);
});
答案 1 :(得分:1)
没有办法像第一个例子那样捕获错误。这里的问题是您使用的是Explicit Promise Construction Antipattern。您正试图让Promise
构造函数执行的操作超出了它的需要。
相反,您应该宣传最小数量的异步功能,并在此基础上构建。在这种情况下,这将涉及产生在解决之前等待一定时间的承诺。大多数第三方承诺库已经有.delay()
方法,但创建自己的方法非常容易:
let delay = duration => new Promise(resolve => setTimeout(resolve, duration));
然后你可以在此基础上构建,并轻松捕获错误:
let delay = duration => new Promise(resolve => setTimeout(resolve, duration));
delay(1)
.then(() => {
throw new Error("uh oh");
})
.then(number => {
console.log("Number: " + number);
}).catch(e => {
console.log("Error: " + e);
});

答案 2 :(得分:0)
“为了这个问题,假设抛出错误的代码部分在另一个命名函数中,因此它无法访问拒绝函数。” - Christopher Shroba
“这个(你的代码中不存在)函数会返回一个Promise吗?” - Jaromanda X
“是的,另一个函数通常会返回一个承诺,但是因为该函数中的异步函数抛出错误,整个函数都会抛出一个错误。” - Christopher Shroba
下次发布您的代码时,因为您用英语描述问题的能力永远不会像实际代码那样好。 “异步函数”是指一个返回promise的函数吗?如果是的话......
错误在你的Promises中的深度并不重要。这是一个示例函数three
,它调用一个函数two
,它调用一个函数one
,它有可能在JSON形成不良的情况下抛出一个错误。每一步都为最终计算做出了有价值的贡献,但是如果one
抛出错误,它将在整个Promise链中冒出来。
const one = (json) => new Promise((resolve, reject) => {
resolve(JSON.parse(json))
})
const two = (json) => one(json).then(data => data.hello)
const three = (json) => two(json).then(hello => hello.toUpperCase())
three('{"hello":"world"}').then(console.log, console.error)
// "WORLD"
three('bad json').then(console.log, console.error)
// Error: unexpected token b in JSON at position 0
否则通过“异步函数”你的意思是它是一个不返回Promise并且可能使用延续的函数?在这种情况下,我们将修改one
以将异步函数包装在promise中,然后two
和three
将起作用。重要的是,我在任何Promise函数中都不使用try
/ catch
// continuation passing style async function
const asyncParse = (json, k) => {
try {
k(null, JSON.parse(json))
}
catch (err) {
k(err)
}
}
// one now wraps asyncParse in a promise
const one = (json) => new Promise((resolve, reject) => {
asyncParse(json, (err, data) => {
if (err)
reject(err)
else
resolve(data)
})
})
// everything below stays the same
const two = (json) => one(json).then(data => data.hello)
const three = (json) => two(json).then(hello => hello.toUpperCase())
three('{"hello":"world"}').then(console.log, console.error)
// "WORLD"
three('bad json').then(console.log, console.error)
// Error: unexpected token b in JSON at position 0
哦,如果你有一个函数f
,它在这两种方式中都不起作用 - 即抛出错误但不返回promise或将错误发送到continuation的函数 - 你“处理一块垃圾,而你编写的代码依赖于f
也将是垃圾。