Unsubscribe to a PubNub channel in response to (before)unload event - javascript

I am building a multi-players game in angular using the PubNub service, including the presence add-on.
Since I need to detect if someone left the game unexpectedly - in order to send a message to the other players and end the game - I am trying to unsubscribe a user when he refreshes the page or goes to some other url. However, in Chrome - as opposed to FireFox - no presence event is being triggered, which probably means that the user wasn't unsubscribed prior to his leaving of the page.
CODE:
$(window).bind("unload",function(e) {
PubNub.ngUnsubscribe({channel:$scope.game.channel});
e.preventDefault();
});
I am aware that these events (beforeunload and unload) are problematic and have poor browser support, which is probably the reason for the failure. If this is the case, is there any other cross-browsers detection method I can use?

There is no reliable way to catch the browser closing. The "beforeUnload" event is your best shot, but most mobile browsers don't trigger it. The best way to handle a user closing the browser in PubNub is to specify a heartbeat when subscribing (http://www.pubnub.com/docs/javascript/api/reference.html#subscribe). The heartbeat tells how many seconds PubNub should wait after an ungraceful disconnect (such as closing the browser), before considering a user as timed out. This is defaulted to 320 and can be set to as low as 6 seconds (> 5). It still won't be immediate, but you will receive a presence "timeout" action 6 seconds after the browser is closed. Having a low heartbeat could impact your battery life so be wary of that.
Also, I know I linked the doc to the JS API, but the angular ngSubscribe allows most of the same arguments.
Hope that helps.

Related

Can a service worker update the cache without an open tab?

I want to give the user a speed feel when he accesses my website. If I cache the initial page in service worker, then I can achieve it. But I am having the following doubts.
Is there any way to update that cache even user does not have any tabs with my website?
Is there any memory limitation?
1) Not in a simple way - your Service Worker is suspended until something wakes it up, for example the user opening your app. Or the push message. So you might run your cache update flow in a push message handler and send the push to all subscribed users whenever the update should happen. But you have to be aware that there are limitations of how many pushes can the app receive and/or how long the handler can run.
"Normally" this is done when the new Service Worker version is installing and requires reload (or manual handling) to take effect.
2) Yes, the general storage limit applies. It is OS-specific and you can query for the estimate with Quota Estimation API (Chrome only by now).

Preventing a browser from getting stuck on an AJAX request

I am currently trying to send a request when an user closes the page. I am using the onbeforeunload event.
The event triggers when the tab is closed or the page is refreshed. My event looks as follows:
window.onbeforeunload = function () {
$.ajax({ //jQuery
type: "POST",
url: "offline.php",
data: {
logout: 'false'
}
});
};
offline.php (this is not the complete script):
...
unset($_SESSION["onpage"];
if ($_POST['logout'] == "false") {
sleep(3);
if (isset($_SESSION["onpage"]) || !empty($_SESSION["onpage"])) die();
}
...
When a user closes the page, script unsets a session that is set on the page of the chat. After three seconds, the script should check if the user has returned but checking the onpage session. However, the problem comes in when I hit the refresh button. On refresh, the page does not load because the three seconds have completed. This is causing my whole system to be ruined.
I have tried adding ignore_user_abort(true); but it did not solve my issue. Is there any other way of getting this to work?
Side Note: This is for a chat. When a user closes the page, it should notify the other users on the chat with a "The user has left" message. This should not be displayed on refresh. When a user comes back to the page, it should notify the other users that the user has returned with a "The user has entered" message.
The Problem
I'm afraid what you're attempting to do isn't really possible, as there are many times in which onbeforeunload won't get called, due to browser implementation, user preference, your pet zebra knocking your computer off the table, etc.
From Mozilla's beforeunload documentation:
Note also that various mobile browsers ignore the result of the event (that is, they do not ask the user for confirmation). Firefox has a hidden preference in about:config to do the same. In essence this means the user always confirms that the document may be unloaded.
https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload
The Solution
That doesn't mean handling users going offline is impossible, however.
Most chat web applications instead employ a heartbeat (a regular ping-like request), and use the distance between last ping to determine user disconnects. As an additional note, I would recommend allowing a wider window than three seconds to determine user disconnects, because there are many reasons a ping may not make it within a three second timeframe.
Implementation Strategy
You have a few options to implement a ping. Most commonly, people will use a window.setTimeout to invoke the ping, which will restart the window.setTimeout upon completion or failure, usually doubling the delay on successive failures so you aren't barraging a potentially-overloaded service.
setTimeout to Ping:
var i = 1000;
(function ping() {
$.ajax({
type: "POST",
url: "ping.php"
}).done(function() {
i = 1000;
window.setTimeout(ping, i);
}).fail(function() {
i = i * 2;
if (i > 60000) {
// We don't wait to wait longer than a minute
i = 60000;
}
window.setTimeout(ping, i);
});
}());
What about window.setInterval instead? Won't my code be shorter?
Please don't do that. My above note about "barraging an overloaded service"? It'll be plenty worse if you do that.
You really shouldn't be counting on onbeforeunload or beforeunload since a browser shouldn't require itself to do something on your behalf right before a user closes your webpage. If it did, it would open up a whole avenue of attack for malicious code where you could never close a page (think going to a torrent website and having 2 pages pop up every time you click on any DOM element, only now every time a user tries to close the tab, a recursive loop starts and prevents them from ever leaving without killing the browser through task manager).
Heartbeats
Most chat clients use a heartbeat system where the client automatically pings the server every x seconds. This method works - but it's costly and inefficient. You're forced to open and close new connections on a constant basis just to tell the server that you are still engaged.
Web Sockets
The contemporary way of building something like a chat system is to use web sockets. These are persistent connections established by the server between your web browser and the server. On a traditional web page, the server always reacts to the what the client does. The client makes a request, the server responds; this process repeats itself over and over again. The server never tells the client what to do and then wait for the client response. With web sockets, instead of having this one way communication channel, we have a pipeline that allows for a continuously open connection with bidirectional communication.
Creating Web Sockets
This isn't a trivial task. There's a lot of boilerplate code out of the gate you would have to write to get some basic functionalities working. But the good news is that you don't have to do this. There are several 3rd party JavaScript SDKs / back-end services that encapsulate all of the ground level browser implementation logic for you and make available to you a simple, clear interface. Think of their relationship to web sockets as what jQuery was to plain JavaScript. They standardize everything for you so you don't have to worry about writing low level web socket implementation and syncing up cross browser compatibility.
One of my favorite web socket services is Firebase. Coincidentally, the demo project they showcase on their website is a real-time chat application built using the web socket support their service provides. Firebase can be set up to be an indepedent database source if you want it to be that. Or it can simply be used as a medium of communications between your traditional SQL database (which communicates with it through a RESTful API) and client devices (browsers, apps, etc...).
I would like to point out that, as others have said, doing an AJAX request on the page unload event is highly unreliable.
However, you may be interested in Navigator.sendBeacon()
Relevant excerpt:
This method addresses the needs of analytics and diagnostics code that typically attempt to send data to a web server prior to the unloading of the document.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
It is experimental, but once fully supported, should do what you want.
AJAX can get cut off as the page leaves.
You need to use navigator.sendBeacon() instead.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
window.addEventListener('unload', function () {
navigator.sendBeacon("offline.php", {
logout: 'false'
});
}, false);
This is simple, reliable, and needs no server smarts like juggling heartbeats entails.
Of course, like anything good in webdev, IE compat is lacking...

Session Timeout in Fiori: Does SAP UI5 or the Gateway layer provide an event which gets called when the user's session times out

I'm working on resource locking in SAP Fiori. To be more elaborate I am trying to lock a resource once a user logs in and opens my application and unlock the resource once he logs out or gets logged out.
I am aware of the onExit() event handler which is located in the main.controller.js and is called if the user performs an action which logs him out. This handles all scenarios except one: when the user's session is timed out.
Is anyone aware of a method(UI5 / Gateway layer) that is called once the session time's out?
As far as I think how this is handled is if a user's session is timed out then nothing happens until the user refreshes the screen.
At this point an Odata call is made to fetch data. Once this hits the Gateway it checks and finds out that the session has timed out and triggers a relogin action.
Correct me if I'm wrong. If right does anyone know what is the event handler which does that?
Also I have read up quite a bit about this. This falls under optimistic and pessimistic concurrency. I would like to try a pessimistic apprach and not a optimistic
approach using etags.
Thanks in advance for your time.
Also I cant officially post any code as it would be against policy, but if you have any queries please feel free to ask and I will do my best :). Plus this is more a fact finding mission.
There is no way you can trust a request to be executed from a browser to signal time out. You will end up with locked resources that shouldn't be locked due to lost connectivity, app crashing, battery drain to name a few. A classic problem for web applications!
Instead, you can construct a lock refresh mechanism. Refresh the lock every 30 seconds or so in the background. Just make sure to fetch the latest version of the resource if the lock was ever released!

What's the best way for background polling in Windows 8 Metro apps?

I'm working on a Win 8 javascript app that has rss-reader-like capabilities. It should repeatedly check a server for new posts and display a toast, if a new post was found.
My question is, if I should use a background job with a time trigger (that is limited to an interval of 15 minutes) or if a setTimeout / setInterval wouldn't be the better way.
As far as I understand the app lifecycle, my app can be suspended by Windows at any time it is not focussed and Windows decides that timepoint on itself. And if the app is suspended once, neither background jobs will work, nor will the setTimeout / setInterval fire.
If I may, I'd suggest rethinking the notification mechanism here.
If you want to use a toast notification, I'd suggest a push notification. It does require a require a cloud service that does the polling of articles for you and then pushes the notification to subscribing clients; however, it won't tax the battery life of the client nearly as much as a polling trigger.
An issue with toast notifications is that they can be easily missed, so if you want to inform the user of unread articles, you may want to consider a badge notification that will persist on the application tile (like you see on the Mail application). Then at a glance the user will know there are unread articles, versus knowing that only if they happened to see the incoming toast.
Tile and badge notifications can also be updated periodically, which is similar to what you wanted to do with toast, but the mechanism for doing so is much easier. The challenge here though is that periodic notifications aren't generally personalized, that is every user of your app would see the same badge/tile unless you did a bit more work on the server side.

Resuming JS timer on accidental power failure

I am making an online quiz app having a timer which is implemented through JavaScript. If accidentally, the browser closes due to power failure, I intend to resume the timer from the time-point when the browser was closed. Right now, I am recording time only at the end of the quiz in a database using PHP/AJAX. How can I resume from the exact time when the user closed the browser?
The issue with a power failure is that you will not be notified in advance of the power going out so there is no opportunity to save state upon the power failure.
Thus, the only way to have any idea when the power went out is to be continuously saving state every N interval of time. Then, when the power goes out and is then restored, you can look at the last saved state. It won't be perfect, but will be the best you can do.
Your three options for saving state are:
Set a cookie every minute (or some period of time with the running count of time in it).
Save the same state to local storage (newer browsers).
Do a form of "auto-save" of the running time to your server with a regular ajax call (every few minutes).
The advantage of options 1 and 2 is that it's all client-side so saves are quick and don't load your server. The disadvantage of options 1 and 2 are that they could conceivably be manipulated by a client trying to game the system.
There's a small danger that even the local state in options 1 and 2 might not be saved properly in a power outage, but as best I know most browsers do persist this to disk when it's saved so that it's reliable even if the browser later crashes.
You can subscribe to the window unload event, but I'm not 100% sure this will be fired on a power failure shutdown.
Perhaps a better solution would be to poll the user during the course of the quiz by a setInterval which can fire off every 1000ms (or however frequently) and set/update a cookie.

Categories

Resources