I'm building a pwa for a client that will list upcoming tasks for their employees. They will often be in areas with poor mobile service so the intention is that records are downloaded whenever they have data and then loaded locally from indexeddb.
My original intention was to use "periodic sync" until I realised that the maximum refresh time was once every 12 hours.
Next I moved onto regular background sync, with the js app sending a sync request to the service worker, and the service worker running the functionality on ExtendableEvent.waitUntil as in Google's background sync example:
self.addEventListener('sync', function(event) {
if (event.tag == 'myFirstSync') {
event.waitUntil(doSomeStuff());
}
});
What I've found however is that event.waitUntil only seems to re-attempt the call every 5 minutes and I want a much faster refresh rate (more like every 30 seconds).
I kind of have 2 questions - first, is it possible to speed up the retry rate on waitUntil.
Perhaps more importantly, is this even a helpful strategy? It seems to me that my app could just repeatedly call the update function without even bothering the service worker. What advantage do I actually get from background sync?
Is there anything else in the pwa toolkit that would better suit my needs?
The benefit of (regular, "non-periodic") background sync is that the lifetime of the retries extend beyond the lifetime of your web app being open. Once the sync eventually succeeds, you could do something like show a notification (assuming the user has granted permission) that will take the user back to your web app to continue working.
Because this feature involves running code in the background, with the browser open but the web app potentially closed, there are limits imposed by the browser on how often the code will run. You can't increase the frequency of the retry attempts.
But you can definitely implement retry logic outside of the context of the service worker and background sync, by running code at the frequency you desire from within the context of your web app itself. But in that scenario, the retries will cease as soon as the user closes your web app.
Related
Assuming:
User has allowed notifications on my website.
Service worker is installed and ready.
User sets a client side reminder to be reminded 24 hours from now.
No backend service or server to push the notification to the user.
How can I trigger a desktop notification if there is no backend server to push that notification? Is this possible?
The service worker will be shutdown by the browser if provided a timeout/interval and the web-alarm/task-scheduler specification is not yet ready for use. Is there no client side only approach to trigger a notification at some designated time in the future?
Is there a desktop notification that is strictly not a "push notification"? A push notification, by nature, is pushed from a server. Can a notification be triggered from the client side?
I do not believe this is possible at this point in time.
Push notifications are specified in RFC8030, from its abstract:
This document describes a simple protocol for the delivery of real-
time events to user agents. This scheme uses HTTP/2 server push.
Which implies the requirement for a server supporting HTTP/2 push.
I do love to rant at Javascript, and I do not seem to be able to find an Javascript implementation of an HTTP2 server to run in the browser (there is for node), which is a shame for me, and would be awesome to mock about.
So, looking for fame, http2-server.js is missing.
You might be able to consider using localStorage. However, this is only beneficial for users that utilize the same device and browser.
Below is a function that kicks off on page load. If you want it to occur periodically throughout a session, you could wrap it into a setInterval and check periodically. This is assuming it needs to be exactly 24 hours later to the millisecond.
// on page load
window.onload = () => {
const dayMs = 24*60*60*1000; // 1 day in milliseconds
const notificationTimer = localStorage.getItem('notificationTimer');
if(notificationTimer){
const sendNotification = (Date.now() - (new Date(notificationTimer)).getTime()) > dayMs;
if(sendNotification){
const notification = new Notification('Displaying next day reminder from yesterday');
}
}
};
When the user selects the next day reminder you can then set the notificationTimer:
localStorage.setItem(notificationTimer, Date.now());
You'd have to make some caveats about the next day reminder not working across browsers or devices, which may or may not be desirable.
As things stand while writing this (3rd Jan 2019):
There is no "desktop notification" that is not strictly "push notification" and works well cross platforms.
It is not possible to trigger a "desktop notification" without your app working in the background.
Service workers are not supposed to use timers and will be shut down.
The Operating System or other utility software may also suggest or even shut down your background application.
There is no client side only approach to trigger your notification at a precise time in the future. There are too many reasons for organisations not allowing this to happen at present.
Your only choice seems to be to use a different Push Notification Service coupled with an external scheduling service that would trigger the external notification based on custom schedules.
Your requirements as I understand them:
Each visitor would need to subscribe to push notifications
Record externally customer preference (for example: using some cloud scheduling)
Use the external scheduling service to trigger the push notification service.
PUSH NOTIFICATIONS are SERVER TRIGGERED not CLIENT REQUESTED
The main point of push notifications is that you should trigger the notification externally to avoid using resources on the end user device. This does not stop you collect notification preferences from users, save this information externally so you can trigger a notification externally when needed.
More information about PWA notification can be found in the following article:
https://developers.google.com/web/fundamentals/codelabs/push-notifications/
As far I know PWA Service Workers should not use timers!
As an alternative to using the PWA notifications, you may want to rightly consider using different notification service. For example FCM https://firebase.google.com/docs/cloud-messaging/
The idea could be to save externally the notification preference of the user and trigger the FCM notification via another cloud service when the scheduled time is reached.
Obviously those notifications will only ever work if the users are connected to the network. However this would have been also the case with any Notification service requiring network access.
I hope the above helps, Cheers and happy codding!
Assuming the notification data on your website will not be sent from the server. Using local storage will be the way to go.
You can store a variable to help track when to show the notification anytime the user hits your website:
localStorage.setItem("lastNotification", Date.now());
So you can have a script that does the following;
function notificationHelper(){
var lastTime = localStorage.getItem("lastNotification");
if(Date.now - lastTime > 86400000){
//Logic to show notication here
//set a new time at the end of the logic
}
//Otherwise Do Nothing
}
Hello I am developing an auction app like tophatter.com. I want to implement an application that has background process in it. I want this process to run forever until I stop it
http://eoction.com thatss our current site. The problem on our site when we refresh the page the auction also restart. We need something like a continuous process like tophatter.com if you refresh the page it will load the updated auction process.
I found this great service called pubnub. I am thinking we need a background process for this? This will process the auction on the pubnub blocks and then when we visit the site we will just need to query on its updated process?
Does pubnub support something like this?
PubNub Web Page Best Practices
When user refreshes your web app page or navigates to another page there are things you need to consider as a web app developer no matter what technologies you may be using. I will address, at a high level, the things you need to do when PubNub is integrated into your web page.
Restore Parameter
Whether the user interrupts your connection to PubNub or it is a network failure, you will want PubNub to reconnect and continue where it left off as much as possible. The PubNub JavaScript SDK has a initialization parameter called restore that when set to true, will reconnect to PubNub and get missed messages after the connection is dropped and reestablished.
var pubnub = new PubNub({
subscribeKey: "mySubscribeKey",
publishKey: "myPublishKey",
ssl: true,
uuid: getUUID();
restore: true
});
Reuse UUID
It is important to reuse the same UUID for each end user as this will allow PubNub to identify that user uniquely when it comes to Presence so that it doesn't produce new join events for the same end user. The PubNub JavaScript SDK actually generates a UUID and stores it in localStrorage and reuses it by default but very likely you have your own UUID that you would like to use for each of your end users.
Last Message Received Timetoken
If the network disruption is brief as is the case with a page refresh or page navigation, then missed messages are retrieved when restore:true is implemented in the init as stated above. But when the user is offline for more than say 5 minutes, you may want to retrieve missed messages on one or more channels. The best way to do this is to keep track of the timetoken of the last received message by storing it in localStorage every time a message is received via subscribe callback. When the user comes back online and it is has been more than 5 minutes since they were last online, call history using this last received message timetoken on each channel that you need to get missed message from.
Subscribe to Channels
Finally, you'll want to make sure that the user is subscribed to the channel they expect to be based on what their state prior to the connection disruption. If it is a page refresh, you likely just want to resubscribe them to the same list of channels. To do this, you just need to keep a list of channels they are currently subscribed to, once again, in localStorage. If the user navigates to a new page and this causes a full page reload (modern web apps should not require this, but...) then you may want to unsubscribe from some channel(s) and subscribe to new channel(s), it just depends on what that page navigation means to your app. Modern web app frameworks do not require full page reload for page navigation since the web app acts more like a desktop app than older web apps. And again, if the the user was offline for quite some time (more than 5 minutes) then it may not make sense to subscribe them to the same channels that they were subscribed to before. Really depends on your use case.
And by the way, Tophatter uses PubNub ;) but all of the above are generic best practice guidelines and recommendations and is not referencing any one app in particular.
EDIT: To address you question specifically, as pointed out in comments below...
You can't implement long-running process in PubNub BLOCKS (not currently, anyways), so you will need a server process for this. When the user refreshes the page, you just need to hit your server for current state. If using PubNub to keep this progress bar updated in realtime, you just subscribe to that channel that is sending the state of that progress bar and update your client. Using the same best practices I provided above are still necessary.
Can i make a service worker, that run in background and poll the server at specific interval and return response or show notification(push notification) when chrome browser is closed. I am working for a website, that ask for service worker permission and sync the request at specific intervals in background based on request received from server show the notification.
Edit 1:
As of now i can see chrome is working on this, but the post is too old Dec 2015. They have written it that they will introduce it in first half of 2016. It is not available till yet.
We're aiming to ship background sync to a stable version of Chrome in
the first half of 2016. But we’re also working on a variant, “periodic
background sync”. This will allow you to request a “periodicsync”
event restricted by time interval, battery state and network state.
This would require user permission, of course, but it will also be
down to the will of the browser for when and how often these events
fire. E.g., a news site could request to sync every hour, but the
browser may know you only read that site at 07:00, so the sync would
fire daily at 06:50. This idea is a little further off than one-off
syncing, but it’s coming.
According to this post https://code.google.com/p/chromium/issues/detail?id=429419 as well as some testing I did to verify the limit is real - I understand that number of WebSockets I can open is limited.
Problem is that I sometimes need more than 30 websockets, because a user might open 30 tabs.
I was wondering what would be the best possible way of maybe sharing a pool of webSockets between different tabs. Here are some ideas I had in mind, and I would love to hear other possible ideas:
Allocate a webSocket pool in one main window, as a globally reachable element and then make sure all other tabs are children of that main page. Then I can use an inter-tab communication:
window.parent...
Problem is that not all tabs are created as child windows of the main window, and that main window might be closed.
Allocate a webSocket pool somehow "in the local storage" - I am not too familiar with the local storage, but I think that at the very least it can hold somehow a reference to a master tab that is currently managing the webSockets. Every once in a while, other tabs try to set themselves as a master tab.
I know its sounds awful and cumbersome. But how possible is it to write a thread/proccess safe code when accessing the local storage? Any example will be appreciated.
Would love to hear any other suggestions you might have.
Number 2 won't work, because LocalStorage is limited to string types.
I would recommend looking at ServiceWorkers.
A single service worker can control many pages. Each time a page within your scope is loaded, the service worker is installed against that page and operates on it.
This sounds pretty close to what you want. Register a ServiceWorker that simply accepts messages and rebroadcasts them to clients - any page from your domain. So you can have one main page that creates the WebSocket connection, and every time it gets a push it will broadcast a message through the ServiceWorker messaging system. Other tabs can pick up on it as needed.
Alternatively, you could use a shared WebWorker on the same principle. Just install it as a messaging system that broadcasts the messages from your WebSocket.
These aren't exactly the intended uses for these technologies... but if it works it works.
I have a web application to be run on mobile phones that when open continuously generates data (a few kilobytes every few seconds or every few minutes depending on settings) and needs to push it to a server in real time. No data is ever sent from the server to the browser.
My main concern is to make this submission battery efficient, a few seconds of delay is totally fine.
I envisaged two solutions:
Periodically do a POST to the server with the data (to avoid having a permanent connection to maintain)
Have an open websocket and periodically send messages (to avoid the weight of an http request)
Which one is the most efficient for the battery? Are there other strategies that I am missing?
Actually my app will be hosted on heroku, which does not supports websockets yet, resulting in long polling, thus for the moment I'll assume it is better to POST on demand, but I am wondering if it could be an option in the future (or maybe this assumption is wrong).
Android
On Android devices, there are three different network radio states as the documentation says:
The state machine for a typical 3G network radio consists of three
energy states:
Full power: Used when a connection is active, allowing the device to transfer data at its highest possible rate.
Low power: An intermediate state that uses around 50% of the battery power at the full state.
Standby: The minimal energy state during which no network connection is active or required.
While the low and idle states drain significantly less battery, they
also introduce significant latency to network requests. Returning to
full power from the low state takes around 1.5 seconds, while moving
from idle to full can take over 2 seconds.
The device changes from Full to Low after an idle time of 5sec, then from Low to Standby after another 12sec.
The above link also covers some best practices for battery friendly connections, although it doesn't say anything specific about Websockets.
iOS
I couldn't find such specific documentation on iOS devices, but the model seems to apply in a similar way:
Cellular and Wi-Fi radios are designed to power down when there is no
activity. Depending on the radio, though, doing so can take several
seconds. If your app transmits small bursts of data every few seconds,
the radios may stay powered up and continue to consume power, even
when they are not actually doing anything. Rather than transmit small
amounts of data more often, it is better to transmit a larger amount
of data once or at relatively large intervals.
So what?
In general, you should probably use short POST requests and send data as seldom as possible, so the radio can power down in between.