Joe Attardi
Joe Attardi

Reputation: 4521

Multiple successive effects not completing?

I'm not sure if the title of this post explains my problem well, but here is my situation.

I have a tree with lazily loaded children. When you expand a tree node, it dispatches a LoadChildrenAction with the parent node that was just expanded as a payload.

Here is my effect:

  @Effect()
  loadChildren$: Observable<Action> = this.actions$
    .ofType(ActionTypes.LOAD_CHILDREN).switchMap((action: LoadChildrenAction) => {
      return this.categoryService.loadChildren(action.payload).map(
        children =>
          new LoadChildrenSuccessAction({
            parent: action.payload,
            children
          })
      );
  });

If I expand just a single node, this works perfectly. The LoadChildrenSuccessAction is dispatched and in my reducer I update the tree.

However, if I expand a node, then expand another node before the first operation completes, only the last operation ever completes.

That is to say, I expand one node, then immediately expand another node while the first node is still loading. The second tree node gets updated with its child content, but the first one never does. In fact, two LoadChildrenActions get dispatched - one for each expansion - but only one LoadChildrenSuccessAction ever gets dispatched.

If I put a console.log inside my categoryService.loadChildren function, it gets logged twice - so the service is getting called twice. But only one action gets dispatched, so I lose the first action - it just never completes.

Any idea what I'm doing wrong here?

Upvotes: 2

Views: 352

Answers (1)

Explosion Pills
Explosion Pills

Reputation: 191799

This is because you are using .switchMap which will cancel a previous observable if it has not completed before the next observable is emitted. The first loadChildren is called, and when the second is called before it completes the first call is canceled.

You can use .mergeMap instead which will allow you to run multiple calls of loadChildren in parallel. Just keep in mind that this removes the somewhat automatic canceling of duplicate requests so if you need functionality like that you'll have to handle it on your own.

Upvotes: 4

Related Questions