Handling service calls when network connection intermittently goes offline

First of all, you owe it to the application users to ensure that your application still works if the network connection goes down, at least when it comes to reading data. For that situation, it would be nice if we could answer with localStorage if the HTTP response fails to deliver. This, however, means we need logic in our service that works in the following way:

if(networkIsDown) { 
/* respond with localStorage instead */
} else {
/* respond with network call */
}

Let's take our service and modify it slightly to account for being offline:

export class TaskService {
getTasks
() {
this.http
.get<Task[]>('/data/tasks.json')
.do( data => {
localStorage.setItem('tasks', JSON.stringify(data))
})
.catch(err) => {
return this.fetchLocalStorage();
})

}

private fetchLocalStorage(){
let tasks = localStorage.getItem('tasks');
const tasks = localStorage.getItem('tasks') || [];
return Observable.of(tasks);
}
}

As you can see, we do two things:

  • We add the .do() operator to carry out a side effect; in this case, we write the response to localStorage
  • We add the catch() operator and respond with a new Observable that contains previously stored data or an empty array

There is nothing wrong with solving it this way, and in a lot of cases, it might even be good enough. What happens when data arrives from many different directions, though, as suggested earlier? If that is the case, then we must have the ability to push data into the stream. Normally, it's only Observers that can push data with observer.next().

There is another construct, though, the Subject. The Subject has a dual nature. It has the ability to both push data to the stream and it can also be subscribed to. Let's rewrite our service to account for the external arrival of data and then add Sock.io library support so you will see how this is scaled. We start by making the service stateful. It would be tempting to just code it like this:

export class TaskService {
tasks: Task[];
getTasks() {
this.http
.get<Task[]>('/data/tasks.json')
.do( data => {
this.tasks = mapTasks( data );
localStorage.setItem('tasks', JSON.stringify(data))
})
.catch(err) => {
return
this.fetchLocalStorage();
})
}
}

The preceding changes we propose are bolded and entail creating a tasks array field and doing an assignment to the tasks field with the arriving data. This works, but it might be more than we need.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset