⚠️ This lesson is retired and might contain outdated information.

Improve Server Communication in Ngrx Effects with NX Data Persistence in Angular

Lukas Ruebbelke
InstructorLukas Ruebbelke
Share this video with your friends

Social Share Links

Send Tweet
Published 5 years ago
Updated a month ago

Communicating with a remote server via HTTP presents an extra level of complexity as there is an increased chance of race conditions and the need for error handling. There is also the tricky problem of how to handle the user experience as the application is trying to complete the remote request. NX Data Persistence is a library that works with ngrx effects to give us a better way to handle remote server calls as well as improving on the overall shape of the effect itself. In this lesson, we are going to convert our stock effects to use NX Data Persistence and the advantages of doing so by using fetch, optimisticUpdate, and pessimisticUpdate. We will also see how it gives us a neat division in our effect to handle the sequence we want to run as well as any errors that should arise in the process.

Instructor: [00:01] In this lesson, we are going to learn how to improve upon our server side HTTP communication with data persistence from NgRx. This is perfectly acceptable to use NgRx effects out of the effects.

[00:17] I find that, because there's so many ways for HTTP communication to go awry, from raise conditions to error handling, etc., that the data persistence library is a better tool for the complexities of that kind of server side communication.

[00:35] As well as I just prefer the underlying shape, as I find it to be a little bit more intuitive when you're working with it. We'll go ahead and go to the bottom of the class. Let's update our dependencies that we're injecting into the constructor.

[00:53] We'll go ahead and create a new line, and we'll go private dataPersistence. Then we will go ahead and just import dataPersistence, and strongly type this with project state. Then from here, let's go and update our load projects effects.

[01:18] We'll go ahead and comment out the existing effect, and then we'll create a data persistence equivalence, so this.dataPersistence.fetch. This is going to take two parameters. The first one is going to be the object type that we want to listen to.

[01:38] This will be of load projects. Then the second parameter is going to be just an object literal. Now, there are a few parameters that we can put on this object. The first one that we care about is run. We'll go ahead and set this to an empty function.

[01:58] The second one is going to be onError. We'll set this to an empty function as well. We'll copy this, and we're going to update the add projects effect with this same thing. The difference is, we're going to update the project type, as well as change the method we're going to call to pessimisticUpdate, meaning that it's going to make the server side call, and then it's going to update the UI.

[02:28] Versus optimistic, which is it'll update the UI, and then make a call to the server. If something goes wrong, you have to undo it. In our little projects, on the other hand, we're just calling fetch. It's just a straightforward call that doesn't have a UI dependency in the workflow.

[02:49] In our run block, let's go ahead and add in our action, which is load projects. Then the second parameter is our project state. This is really handy when we need to pull something additional from our future state.

[03:07] Now, this is where what we would have handled in the switch map in our regular effect, this is where this functionality goes. We're just going to in here return the result of this.projectServiceAll, and then we'll go ahead and map that result to a new completed action object.

[03:26] New project's loading, and we'll just send that result in. Then on error, we're just going to go ahead and just take this error object, and we're just going to trace it out. We're not going to do anything really fancy here, but this is where you would want to put something in, possibly a little bit more robust.

[03:52] Then within our add projects effect, we can do the same exact thing. We'll fill out the action that we want to pass in, project state. Then we'll go ahead and make a call to our project service, so this.projectService.create.

[04:16] Then from here, we'll pass in the action payload. This is slightly different than the effect above. Then we'll go ahead and map the result into a new action object that will then, once that result comes in, it will then be dispatched into our reducer.

[04:43] Just to do a quick review of what is happening, that our new effects have two main blocks in here that runs. With dataPersistence, it's run and onError. This gives you a very distinct place to go ahead and handle your errors, as well as your run block, and as well, you have fetch.

[05:10] Also, pessimistic and optimistic update, depending on the strategy you have for updating your in-memory state, versus your remote state. We can go ahead and we'll just paste in the completed update and delete effect, so that you can see same exact shape, with the trigger action coming in and the completed action going out.

[05:40] There we have it, dataPersistence.fetch, and we also have where we need to update the UI. Then we can do a pessimistic update. You can see that here it is, working. This is how you would do the equivalent of an NgRx effect with the Nx, or Nrwl, data persistence layer.

Oscar Lagatta
Oscar Lagatta
~ 5 years ago

Hi Lukas,

when you talk about having an error handling a bit more robust could you please share what would be the correct approach and a link to an example using the NX DataPersistence?

Thank you!

Lukas Ruebbelke
Lukas Ruebbelkeinstructor
~ 5 years ago

Hey Oscar, A pattern I have used is creating an additional error handling action and slice of state within a feature. So in the project actions:

export class HandleProjectError implements Action {
  readonly type = ProjectsActionTypes.HandleProjectError;
  constructor(public payload: Error) { }
}

and in the effect:

onError: (action: LoadProjects, error) => {
  return of(new HandleProjectError(error))
}

and in the reducer:

case ProjectsActionTypes.HandleProjectError: {
  return { ...state, error: action.payload };
}

and so on through the selectors and facades.

Markdown supported.
Become a member to join the discussionEnroll Today