Is it possible that the onerror callback can be called where onclose will not be called immediately after? In other words, is it possible to get a WebSocket error which does not coincide with the connection then being closed?
If it is possible, I would like to test this case. I have a mocked backend which uses node.js and express-ws. What can I do in the backend to trigger the onerror event callback in the front end.
The error event will only ever be fired prior to then also firing the close event, at least by implementations that properly implement the specification, i.e. you will get error and close as a pair, or just close by itself.
The process for closing a websocket consists of 3 steps, the second of which optionally fires the error event if needed:
If the user agent was required to fail the WebSocket connection, or if the the WebSocket connection was closed after being flagged as full, fire a simple event named error at the WebSocket object. [WSP]
Before the third step then calls close:
Fire an event named close at the WebSocket object, using CloseEvent,...
And because both of these steps are one after the other inside the same queued task, your event handlers should be invoked one after the other, with no other events or tasks taking place in between them.
Related
So I am in the process of migrating a MV2 extension which used persistent Background pages to MV3. In the Chrome migration guide [https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/#event_listeners]
it says :
In order for Chrome to successfully dispatch events to the appropriate
listeners, extensions must register listeners in the first turn of the
event loop. The most straightforward way to achieve this is to move
event registration to the top-level of your service worker script.
When a service worker is terminated, so are the event listeners
associated with it. And since events are dispatched when a service
worker starts, asynchronously registering events results in them being
dropped because there's no listener registered when it is first spun
up.
My question:
Why do we have to register it like that? What's the issue if we register after awaiting an asynchronous operation?
If indeed When a service worker is terminated, so are the event listeners associated with it, then how come an inactive service workers suddenly becomes active, if event listeners are all terminated? (I assume it isn't listening for events if event listeners are terminated.)
// background.js(service worker)
chrome.storage.local.get(["badgeText"], ({ badgeText }) => {
chrome.action.setBadgeText({ text: badgeText });
// Listener is registered asynchronously
// This is NOT guaranteed to work in Manifest V3/service workers! Dont do this
chrome.action.onClicked.addListener(handleActionClick);
});
Why do we have to register it like that ?
Because this is how event registration is implemented internally:
When the background script wasn't running, it's started in a new JS environment and the entire script runs from the first line to the last.
When it calls addListener for chrome events, the API stores the function reference internally.
After the last statement has finished executing, the API calls the function(s) for the event that started the background script.
After all open ports are closed and all events are processed the inactivity timer fires (30 seconds in Chrome) and the script is terminated, the JS environment is entirely destroyed.
Whats the issue if we register after awaiting an asynchronous operation ?
When the background script wasn't running before the event, it's started as described above and your belatedly registered listener won't be present in the internal API database, so it won't be called and this event will be lost for you.
Only when the background script is already running before the event is fired, your belatedly registered listener will see the event.
If indeed When a service worker is terminated, so are the event listeners associated with it then how come an inactive service workers become active suddenly ,if event listeners are all terminated ?(I assume it isnt listening for events if event listeners are terminated .)
Indeed, when the background script is terminated it's like closing of a tab, nothing survives, it doesn't listen to anything, there's no "it" anymore.
The wake-up is implemented by addListener remembering the event names and their filters (e.g. in webRequest of webNavigation) in the internal database of the browser process, which happens every time the background script runs (but only in the first turn of the event loop). When an event matching the criteria occurs in the browser, the browser starts the extension's background script and dispatches the event as described in the beginning of this answer.
I have already tried all possible trouble shooting for this. The problem is occuring with a single event handler. the messsage is received from serverside. This i confirmed in the network tab, but the event handler is not invoked and no error is thrown.
objConnection.on("FileTransferAccepted", (res) => {
setTransferStatus(true);
});
This is received in the browser
I have also confirmed that the event handler is attached
Im stuck. cant figure out whats wrong with just this handler. tried renaming the handler still no change.
So I finally found the problem.
I created a connection object in one page and forgot to clean up and stop the connection before navigating to another page. Here I created another connection object and updated the connection id in the db so that im reachable. But even after the component is unmounted. the earlier connection was not destroyed. And the message was received it but that object had no event handler to handle this event. All I did was close previous connection on unmount and everything started working fine.
Summary:
Solution 1: In case you have created multiple connections in different pages or components. destroy these connections by calling the "stop()" method on unmount. Also dont forget to update your new connection id in db.
Solution 2: dont create multiple connections for dfferent pages, use the same object throughout the app.
I'm using a simple chat-client for my react-native chat app which uses WebSocket.
Whenever there's an error on the server side and the chat shuts down, causing an error event on my app, sets the readyState to CLOSED meaning I need to restart and try to re-connect.
I have a list of listeners when the socket connects such as: 'chatMessage', 'error', 'userDisconnected', 'userConnected'.
But the problem is, whenever I recreate the client by doing:
initWebSocket() {
this._chatClient = null;
this._chatClient = new ChatClient({
url: `${Constants.chatUrl}:${Constants.chatPort}`,
log: false
});
}
To then call a connect() afterwards, I create a duplicated event listeners of all of them. So when I send/receive a message, it shows twice as if it was indeed sent twice. This is a look & feel thing, because on the server, it only shows the message was sent once. If I go back to the message list screen and then get inside the same chat, it will update and show only 1 message, not 2. So this is 100% a duplicated event listener being called.
How can I solve this specific issue?
User logs into application and it starts a connection and registers a handler to restart SignalR connection if it is lost like this
connection.onclose(this.restartConnection);
I've looked through HubConnection.ts and I did not find any option to remove onclose handler. It cannot be replaced by an empty method because it stores all registered methods. Then there is only option to remove custom handlers through
connection.off('methodName');
When a user logs out the application stops SignalR connection at it inevitably fires the onclose handler which ends up with an error for me. I want to unregister the handler so the connection will not try to restart itself after the application deliberately stopped it.
I thought of using a flag if it should or should not try to restart the connection but that does not seem right to me. Is there a proper solution to this?
On the latest version of the SignalR client (which still doesn't seem to have a documented way to do this) you can just set the onclose callbacks array to empty yourself: connection._closedCallbacks = [].
We are developing a conferencing application using javascript client.
We have a scenario wherein a user is connecting to one of the applications and after a while needs to connect to another Twilio Application under different sub Account
Second Time when we have to connect to another Twilio application using
Twilio.Device.setup(token, { rtc: true,debug:true });
we get log something like
**[Device] Found existing Device; using new token but ignoring options**
[Device] Unable to receive incoming calls
[Device] Registered listener for event type "error"
[Device] Registered listener for event type "connect"
[Device] Registered listener for event type "disconnect"
[Device] Registered listener for event type "ready"
[Device] Registered listener for event type "offline"
[Device] Invoke listeners for event type "ready"
**[Application-Ready-EvtHandler] Twilio.Device is now ready for connections : ready
[Application-Ready-EvtHandler] Twilio.Device is now ready for connections : ready (Raised Second Time for old Device)**
seems like previous Device is not getting released
(Number of times ready event is fired == Number of times we have to use Twilio.Device.Setup )
and I'm unable to connect to subsequent Twilio applications after connecting to the first.
Subsequently calling
Twilio.Device.connect({ agent: currentUserName, debug: true });
throws an exception i,e, "Error in Actionscript. Use a try/catch block to find error."
How to switch to subsequent Twilio Applications using twilio.js Library?
EDIT:
P.S. Notice that this is an issue in IE and firefox only , which do not support web-rtc standard. In chrome The event handler are invoked as mentioned but it works!
Am I doing something wrong ?
Jash, I'm Megan from Twilio.
Everything you see in your logs is the expected behavior.
If you want to switch between devices you will need to explicitly call .destroy() as mentioned in the docs. This will terminate active and pending connections, triggering the offline event handler. Device will not be able to make or receive new connections until you call Twilio.Device.setup() again.