如何在异步上下文中捕获异常
How to catch exception in async context
当上下文为 async
.
时,我遇到异常捕获问题
这是我的最小可重现代码
const { EventEmitter } = require('events');
const delaySync = function(ttd) {
return new Promise((resolve) => {
setTimeout(() => resolve(0), ttd);
});
};
const myEvent = new EventEmitter();
myEvent.on('something', async () => {
console.log('Event triggered');
// Just delay for 100ms and then throw
await delaySync(100);
throw new Error('Something happened');
});
describe('Events', () => {
it('should catch error', async () => {
await expect(myEvent.emit('something')).rejects.toThrow('Something happened');
});
});
基本上,我有一个事件发射器。它有一个附加在异步事件 'something' 上的回调。内部有一些异步作业,在 100ms
延迟后会抛出错误。
通常我会在玩笑中使用 await expect(fn).rejects.toThrow(...)
捕获此类错误,但是这种情况不同,因为 expect
fn 需要一个承诺,而 myEvent.emit('something')
是常规的非承诺上下文。
在这种情况下,我遇到了一个错误
● Events › should catch error
expect(received).rejects.toThrow()
Matcher error: received value must be a promise or a function returning a promise
Received has type: boolean
Received has value: true
...
(node:20242) UnhandledPromiseRejectionWarning: Error: Something happened
我也用 try-catch 块尝试过,但它不起作用(根本无法捕获);
try {
myEvent.emit('something');
await delaySync(250);
} catch (e) {
expect(e.message).toBe('Something happened');
}
我试过了
// Not throwing because exception is not happening right away
expect(() => myEvent.emit('something')).toThrow('Something happened');
还有这个
expect(async () => {
// Will thow after 100ms
myEvent.emit('something');
await delaySync(250);
}).toThrow('Something happened');
但他们中的任何一个都不走运。
关于如何在这种情况下捕获错误的任何想法?或任何解决方法?
Eventemitter
完全 sync
并且没有解决方法。你能做的就是用eventemitter2模块代替原来的Eventemitter
class。它与 Eventemitter
完全兼容,并允许您使用 async
操作。
var EventEmitter = require('eventemitter2');
const delaySync = function (ttd) {
return new Promise((resolve) => {
setTimeout(() => resolve(0), ttd);
});
};
const myEvent = new EventEmitter();
myEvent.on('something', async () => {
console.log('Event triggered');
// Just delay for 100ms and then throw
await delaySync(100);
throw new Error('Something happened');
// for async emitters pass promisify true.
}, { promisify: true });
describe('Events', () => {
it('should catch error', async () => {
await expect(myEvent.emit('something')).rejects.toThrow('Something happened');
});
}
当上下文为 async
.
这是我的最小可重现代码
const { EventEmitter } = require('events');
const delaySync = function(ttd) {
return new Promise((resolve) => {
setTimeout(() => resolve(0), ttd);
});
};
const myEvent = new EventEmitter();
myEvent.on('something', async () => {
console.log('Event triggered');
// Just delay for 100ms and then throw
await delaySync(100);
throw new Error('Something happened');
});
describe('Events', () => {
it('should catch error', async () => {
await expect(myEvent.emit('something')).rejects.toThrow('Something happened');
});
});
基本上,我有一个事件发射器。它有一个附加在异步事件 'something' 上的回调。内部有一些异步作业,在 100ms
延迟后会抛出错误。
通常我会在玩笑中使用 await expect(fn).rejects.toThrow(...)
捕获此类错误,但是这种情况不同,因为 expect
fn 需要一个承诺,而 myEvent.emit('something')
是常规的非承诺上下文。
在这种情况下,我遇到了一个错误
● Events › should catch error
expect(received).rejects.toThrow()
Matcher error: received value must be a promise or a function returning a promise
Received has type: boolean
Received has value: true
...
(node:20242) UnhandledPromiseRejectionWarning: Error: Something happened
我也用 try-catch 块尝试过,但它不起作用(根本无法捕获);
try {
myEvent.emit('something');
await delaySync(250);
} catch (e) {
expect(e.message).toBe('Something happened');
}
我试过了
// Not throwing because exception is not happening right away
expect(() => myEvent.emit('something')).toThrow('Something happened');
还有这个
expect(async () => {
// Will thow after 100ms
myEvent.emit('something');
await delaySync(250);
}).toThrow('Something happened');
但他们中的任何一个都不走运。
关于如何在这种情况下捕获错误的任何想法?或任何解决方法?
Eventemitter
完全 sync
并且没有解决方法。你能做的就是用eventemitter2模块代替原来的Eventemitter
class。它与 Eventemitter
完全兼容,并允许您使用 async
操作。
var EventEmitter = require('eventemitter2');
const delaySync = function (ttd) {
return new Promise((resolve) => {
setTimeout(() => resolve(0), ttd);
});
};
const myEvent = new EventEmitter();
myEvent.on('something', async () => {
console.log('Event triggered');
// Just delay for 100ms and then throw
await delaySync(100);
throw new Error('Something happened');
// for async emitters pass promisify true.
}, { promisify: true });
describe('Events', () => {
it('should catch error', async () => {
await expect(myEvent.emit('something')).rejects.toThrow('Something happened');
});
}