简体   繁体   English

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

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

Is it possible to catch asynchronous errors using the ES6 .catch syntax of promises? 是否可以使用promises的ES6 .catch语法捕获异步错误? For example, the following doesn't work (the .catch doesn't catch the error): 例如,以下不起作用(.catch不捕获错误):

new Promise((resolve, reject)=>{
    setTimeout(()=>{throw new Error("uh oh")}, 1);
}).then(number=>{
    console.log("Number: " + number);
}).catch(e=>{
    console.log("Error: " + e);
});

But this synchronous version does: 但是这个同步版本可以:

new Promise((resolve, reject)=>{
    throw new Error("uh oh");
}).then(number=>{
    console.log("Number: " + number);
}).catch(e=>{
    console.log("Error: " + e);
});

Is the only solution to do something like the following, using a try/catch block and reject ing the error in the catch? 是唯一能够执行以下操作的解决方案,使用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);
});

For the sake of this question, assume the part of the code that is throwing the Error is in another named function, so it doesn't have access to the reject function. 为了这个问题,假设抛出错误的代码部分在另一个命名函数中,因此它无法访问reject函数。

Thanks!! 谢谢!!

Edit: Here is a more complete example of what I'd like to do, in JSFiddle. 编辑: 这是我在JSFiddle中想要做的更完整的例子。

Use resolve() , reject() within Promise constructor. Promise构造函数中使用resolve()reject() Handle error at either onRejected or .catch() . 处理onRejected.catch()处理错误。

Note, once error is handled, onFulfilled at chained .then() , if any, should be reached, unless throw is used within onRejected or .catch() , to explicitly pass error to chained .then(_, onRejected) or .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); }); 

There isn't a way to catch an error thrown like your first example. 没有办法像第一个例子那样捕获错误。 The problem here is that you are using the Explicit Promise Construction Antipattern. 这里的问题是您使用的是Explicit Promise Construction Antipattern。 You are trying to have the Promise constructor do more than it needs to do. 您正在尝试让Promise构造函数执行更多操作。

Instead, you should promisify the smallest amount of asynchronous functionality and build on top of that. 相反,您应该宣传少量的异步功能,并在此基础上构建。 In this case, that would involve producing a promise that waits for a certain amount of time before resolving. 在这种情况下,这将涉及产生在解决之前等待一定时间的承诺。 Most 3rd party promise libraries already have a .delay() method, but it's very easy to create your own: 大多数第三方承诺库已经有了.delay()方法,但创建自己的方法非常简单:

let delay = duration => new Promise(resolve => setTimeout(resolve, duration));

Then you can build on top of that, and catch the error easily: 然后你可以在此基础上构建,并轻松捕获错误:

 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); }); 

"For the sake of this question, assume the part of the code that is throwing the Error is in another named function, so it doesn't have access to the reject function." “为了这个问题,假设抛出错误的代码部分在另一个命名函数中,因此它无法访问拒绝函数。” – Christopher Shroba - 克里斯托弗Shroba

"does this (non-existent in your code) function return a Promise?" “这个(你的代码中不存在)函数会返回一个Promise吗?” – Jaromanda X - Jaromanda X.

"Yes, the other function returns a promise normally, but because an asynchronous function inside that function is throwing an Error , the entire function is throwing an Error." “是的,另一个函数通常会返回一个promise, 但由于该函数内部的异步函数抛出了一个Error ,整个函数都会抛出一个Error。” – Christopher Shroba - 克里斯托弗Shroba

Well next time post your code, because your ability to describe the problem with English will never be as good as actual code. 那么下次发布您的代码时,因为您用英语描述问题的能力永远不会像实际代码那样好。 By "asynchronous function" do you mean a function that returns a promise? “异步函数”是指一个返回promise的函数吗? If so ... 如果是这样的话 ...


It doesn't matter how deep the errors throw in your Promises. 错误在你的Promises中的深度并不重要。 Here's an example function three which calls a function two which calls a function one which has potential to throw an Error in the event the JSON is formed poorly. 下面是一个例子功能three它调用的函数two它调用一个函数one具有潜力抛出一个错误的JSON形式不佳的情况下。 Each step makes a valuable contribution to the final computation, but in the event one throw an error, it will bubble up through the entire chain of Promises. 每一步都使最终计算的宝贵贡献,但在事件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 


Otherwise by "asynchronous function" you mean it's a function that does not return a Promise and maybe uses a continuation instead? 否则通过“异步函数”你的意思是它是一个不返回Promise并且可能使用延续的函数? In which case, we'll modify one to wrap the async function in a promise, then two and three will work the same. 在这种情况下,我们将修改one以在承诺中包装异步函数,然后twothree将工作相同。 Of importance, I did not use try / catch in any of my Promise functions 重要的是,我没有使用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 


Oh, and if you have an a function f which does not function in either of these two ways – ie function that throws an error but doesn't return a promise or send the error to the continuation - you're dealing with a piece of rubbish and the code you write to depend on f will be rubbish too. 哦,如果你有一个函数f ,它不能以这两种方式中的任何一种运行 - 即抛出错误但不返回承诺或将错误发送到延续的函数 - 你正在处理一块垃圾和你写的代码取决于f也将是垃圾。

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

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