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

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).

Related

How to receive and handle Chrome notifications/push-notification?

I just want to write a small script that does Foo() whenever I receive a push notification from my browser(chrome). I tried to find some stuff out there but all I found was how to send said notifications, but I only want to receive them. Anybody can lead me in the right direction?
I do not own the backend that sends the notifications
There is no frontend, its notification from the browser
I am currently trying with a browser extension, but cant access the notification. I do not know if browser extension is the way to go, that should be clear from my initial post.
If the question is about intercepting notifications that are generated on the web page with the Notification API, this answer explains how: Intercept HTML5 Web Notifications in a browser environment
To sum it up, it consists in the creation of a Proxy as a wrapper of the native Notification in order to hook into its constructor and execute arbitrary code.
If the question is about intercepting Push Notifications then it is impossible because they are based on the Service worker. You can't hook into the service worker, and you can't register your own service worker without overriding the existing one (which will break the web page), as stated in the documentation:
If there is an existing service worker available, the new version is
installed in the background, but not yet activated — at this point it
is called the worker in waiting. It is only activated when there are
no longer any pages loaded that are still using the old service
worker. As soon as there are no more pages to be loaded, the new
service worker activates (becoming the active worker).

Updating localStorage when there's new data from server?

After logging into an app (React.js), I am caching the member data in localStorage as a lot of my components are using it and request only needs to be done upon log-in, ideally.
However, a few properties in this member object may be changed in the backend manually so the frontend doesn't have a way to know whether the member object has changed at all. (Again, ideally, any change to the member object should go through some form submission that directly changes the DB, with which an update can be triggered for the localStorage, but this is not an option at this time.)
Example scenario: There's a generic form in the app to request for additional credits. Customer service will receive an email regarding the request. Credits would be manually updated for Customer A (in DB). If Customer A doesn't re-login (where the get request for member is done), localStorage will still show the old no. of credits.
If this is the situation, what's the best way to go about it?
Don't store member data in localStorage at all so as to keep the data fresh. Just call the endpoint whenever it's needed.
Use sessionStorage instead?
Trigger a refetch when the user refreshes the page / app (although user may not know that they need to do this to update the data).
Suggestions?
Calling the endpoint whenever its needed is ideal if the data is going to change based on things outside of the user's control.
Session Storage is just local storage that gets wiped when the browsing session ends, you'll still have the exact same issue
This doesn't really solve the problem, and it's typically a bad user experience to require the user to perform regular maintenance tasks in order to use your application to the best of its ability
I'd go with just getting the data fresh.
At a high level, you have two choices:
Poll (periodically call the back end to refresh the data)
Open a persistent connection (like a web socket) to the server, and have the server push updates to clients.
The latter option would require a lot of changes, and it changes the scalability of your app, so the former choice seems like the most reasonable option for you.
It's smart to keep using localStorage so you have an offline copy of the data and aren't blocking rendering during page load; you can have a background periodic refresh process that doesn't disrupt the user in the meantime. If your data is mirrored in something like redux or context, then your UI could seemlessly update if/when the data changes.
If you do not know when member has been updated, don't store it. You should query the back end every time you need member. That is the only way to keep the data sync with your database.

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.

Categories

Resources