When working with BroadcastChannel API, I realized that there's a case where if the channel is closed and the developer still try to call postMessage(), there won't be any exception thrown; at least not all the time.
First case
close() is called from the same broadcastChannel instance with postMessage(), error is thrown:
const bc1 = new BroadcastChannel('foo');
const bc2 = new BroadcastChannel('foo');
bc1.postMessage('bar');
bc2.addEventListener('message', (event) => console.log(event.data));
setTimeout(() => {
bc1.close(); // we're calling the close() from bc1, same instant where we will call postMessage later
}, 500);
setTimeout(() => {
try {
bc1.postMessage('bar2');
} catch (error) {
console.error('postMessage error', error);
}
}, 1000);
The code above will throw an exception:
postMessage error
Error: Failed to execute 'postMessage' on 'BroadcastChannel': Channel is closed
Second case
close() is called from the a different broadcastChannel instance with postMessage(), error is NOT thrown:
const bc1 = new BroadcastChannel('foo');
const bc2 = new BroadcastChannel('foo');
bc1.postMessage('bar');
bc2.addEventListener('message', (event) => console.log(event.data));
setTimeout(() => {
bc2.close(); // we're calling the close() from bc2, NOT the same instant where we will call postMessage later
}, 500);
setTimeout(() => {
try {
bc1.postMessage('bar2');
} catch (error) {
console.error('postMessage error', error);
}
}, 1000);
The code above doesn't throw any exception. IMO, it should have thrown an exception instead.
Question
Is there any possible way to detect whether the channel has been closed in the second case? Or if this's a bug, where can I file a ticket?
If you want to play with the MRE, here's the link.
After reading the documentation, I think it is an acceptable behaviour. First of all, here is a Note from the official specification:
Apparently, we need to clean up BroadcastChannel instances to prevent memory leaks. And now, thinking further, if we broadcast messages to different contexts for syncing/exchanging information, we need to create instances there with the same channel name. However, other contexts could be easily closed which induces the clearance of resources for that particular context. Nevertheless, other contexts should continue exchanging messages - the show must go on.
To sum up, I think it is totally fine to not throw an exception because BroadCastChannel is not aware of all its instances. To overcome the problem, you may create a close handler function that will be placed in each BroadcastChannel listener. For ex:
And then you can call bChannel.postMessage('close'); which will close all instances (set a close flag to false). After that, they should throw errors.