Handling POST Requests in Offline Mode

Sakshi Sehgal
5 min readApr 17, 2021

https://github.com/sehgalsakshi/Offline-POST-PWA---Service-Worker

With the advent of PWA, our web apps have actually become progressive long ago. Using service workers, running applications in offline mode is almost like a cakewalk today. But this support for offline availability is actually more of an illusion or actually a pseudo offline application!
Yup, sorry for bursting the bubble for those who’ve just been introduced to the concept of service workers, “Progressing Web App”s are actually not that progressive yet!
But before we understand the reason why, let’s get through a super quick introduction of the service worker, our hero in PWAs.

Service Worker Workflow

Service worker is a simple plain js script that runs on a separate thread and sits between the application at frontend and the actual calls made to server through a specific URI.
Since it sits in between the actual requests made to server, it just “observes” the requests and saves their response in browser cache using a special caches API.

Corresponding to every request, there is a response saved which is served if the application goes offline.

But wait, did I say “every request”? My bad! This is actually what adds pseudo to existing offline functionality!
There are different events the service worker listens to, and performs appropriate tasks. One such event is “fetch” event which fetches the response of an API call for caching. Or for some static files, we can ask this event to successfully save these images response once to cache and for every subsequent call, use the cached version instead of hitting network again and again, thus saving us some latency.

Now the catch here is, “fetch” event can only cache “GET” requests! [don’t believe me? Try out with a POST request and be ready to catch the error yourself!]
The reason is pretty simple, GET requests are idempotent in nature, i.e., no matter how many times we call a GET API, it is not going to change things. It’s a read only action and hence cache-able. But all others (POST/ PUT/ DELETE), they are actually going to make changes to the resource and in response, we’re only going to get a plain “K”, I mean “Http.Ok” or may be a primary key in case of POST. But the primary key cannot be guessed through on working offline and there’s nothing much we can do with simple okay except deciding if we’ve to execute API response in success or error case.
But have we seen any enterprise level application (or any vanilla app for that matter) built purely out of GET requests?

With great problems, comes innovative solutions! So here we’ll deal with handling POST request in offline mode. (Mind you, handling not caching!)

Here instead of getting service worker from workbox, we’ll develop our own service worker script, listening to standard events.
1. install event for installing service worker, adds call to cache API to cache static files
2. activate event for “activating” a new service worker. Previous event was only setting up things, this is actually going to bring current service worker script to the application context.
This deletes all caches registered in cache storage but the latest cache name provided here.
3. Fetch Event
This is the most important event, because it listens to “each and every” request that’s hitting the server. Since it listens to POST too, we’ll use a separate if block to handle POST scenarios.

The basic idea is create a simple js function for every POST request (you want to serve in offline mode) and perform same actions that would have happened if the application was online.
No, don’t read that line again, that’s actually a mess. Let me try to simplify.
Let’s imagine, there’s a web app that currently displays 5 vacant seats to be booked in a cinema (This info was being fetched through a GET request and as discussed cached!).
You wish to book one seat, of course using a post request. Now a successful execution of this request is going to leave us with 4 vacant seats since you booked one for yourself!
So we can assume, in most of the scenarios, POST is going to change response to a GET call if that call is going to be made after it.
So this is exactly what we’ll do in our function we talked about above.

A biggest assumption here is we would be getting a success response on POST API. We’ve to make this assumption since there’s no way to get any response here.
We’ll open the cache of one (or all) GET request, whose response would get affected by this POST call and we’ll make same changes here and save it back to “same cache”.
One part is done, now subsequent GET requests would give us correct result even if we’re offline.
But how do we notify application, to consider this as a success response. Since our main js application follow DOM, and service worker is not managed by DOM, hence there’s no way to have a method call for this communication.

While handling GET (after caching), service worker returns event.respwith to notify application of the response and returns the same cached response data.
We’ll use the same logic here for post but would respond with a dummy response object created without hitting the server and respond with an “Ok” to continue with successful execution.
And for actually hitting these request once application is back online, we can have a timer that checks for network state after certain time period and make “offline post” calls to the server.

And of course, before hitting we would have to save these post requests (along with their payload) in some storage over browser. There are localStorage, sessionStorage etc. All comes with their own pros and cons. Some do not work on IOS (Oh, IOS is another pain!), some have memory constraints. But my personal favourite is “IndexDB”, a NoSQL database offered by browser. I save all my post requests here in JSON format and once a request is hit, I delete the “IndexDB” row to avoid duplicacy.

For code implementation, follow this link. You may thank me later ;)

--

--

Sakshi Sehgal

Full-Stack Web Developer | Technology Agnostic | Java | ReactJS | Python | AWS | CV | NLP | DL! Jack of All.. and in the process of mastering them too!