繁体   English   中英

如何使用JS promises捕获异步错误?

[英]How can I catch an asynchronous error using JS promises?

是否可以使用promises的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 catch中的错误?

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函数。

谢谢!!

编辑: 这是我在JSFiddle中想要做的更完整的例子。

Promise构造函数中使用resolve()reject() 处理onRejected.catch()处理错误。

注意,一旦处理了错误,就onFulfilled在链接onFulfilled .then() onFulfilled ,如果有的话,除非在onRejected.catch()使用throw ,以显式地将错误传递给链接.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); }); 

没有办法像第一个例子那样捕获错误。 这里的问题是您使用的是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); }); 

“为了这个问题,假设抛出错误的代码部分在另一个命名函数中,因此它无法访问拒绝函数。” - 克里斯托弗Shroba

“这个(你的代码中不存在)函数会返回一个Promise吗?” - Jaromanda X.

“是的,另一个函数通常会返回一个promise, 但由于该函数内部的异步函数抛出了一个Error ,整个函数都会抛出一个Error。” - 克里斯托弗Shroba

那么下次发布您的代码时,因为您用英语描述问题的能力永远不会像实际代码那样好。 “异步函数”是指一个返回promise的函数吗? 如果是这样的话 ...


错误在你的Promises中的深度并不重要。 下面是一个例子功能three它调用的函数two它调用一个函数one具有潜力抛出一个错误的JSON形式不佳的情况下。 每一步都使最终计算的宝贵贡献,但在事件one抛出一个错误,它会冒泡通过承诺的整个链条。

 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以在承诺中包装异步函数,然后twothree将工作相同。 重要的是,我没有使用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 ,它不能以这两种方式中的任何一种运行 - 即抛出错误但不返回承诺或将错误发送到延续的函数 - 你正在处理一块垃圾和你写的代码取决于f也将是垃圾。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM