Shamoon
Shamoon

Reputation: 43531

How can I return from an effect with ngrx / angular5 from a callback function?

My effect has:

  @Effect()   /* sends request to httpService with params as login credentials on instance of loginAction. */
  login$: Observable<Action> = this.actions$
    .instanceOf(LoginActions.LoginAction)
    .switchMap(
      action => {
        return this.loginHttpService.login(action.payload)
          .map( (res: any) => {
                const firstName = res.firstName;
                const lastName = res.lastName;
                // const privileges = res.privileges
                const privileges = ['ViewDeliverableDefinitions', 'SubmitDeliverableInstances']
                this.tokenService.setPrivileges(privileges)
                console.log('observable')
                return Observable.create(observer => {
                  console.log('this is 1')
                  this.permissionsService.loadPermissions(privileges, () => {
                    console.log('this is 2')

                    // observer.next({
                    //   type: 'string'
                    // });
                    this.store.dispatch(new LoginActions.LoginSuccessAction({user: res}))
                    // return observer.complete();

                  })
                })
          })
          .catch( (e:any)  => {
            this.store.dispatch(new LoginActions.LoginFailureAction(true));

            return Observable.create(observer => {
              return observer.complete();
            }) 
        });
      });

However, nothing ever gets called from Observer.create. What am I doing wrong?

Upvotes: 0

Views: 792

Answers (1)

Teddy Sterne
Teddy Sterne

Reputation: 14221

There are a couple of things that need to be updated. First map needs to be a switchMap as previously suggested. This is because an Effect must return an Observable that emits an Action. Doing so will cause the inner observable to be subscribed to. Second, instead of dispatching the action manually, the Effect will do this for you and so you need to just emit a new action in each created observable.

Updated code (minus comments):

@Effect()   /* sends request to httpService with params as login credentials on instance of loginAction. */
login$: Observable<Action> = this.actions$
  .instanceOf(LoginActions.LoginAction)
  .switchMap(
    action => {
      return this.loginHttpService.login(action.payload)
        .switchMap((res: any) => {
          const firstName = res.firstName;
          const lastName = res.lastName;
          const privileges = ['ViewDeliverableDefinitions', 'SubmitDeliverableInstances'];

          this.tokenService.setPrivileges(privileges);

          return new Observable<Action>(observer => {
            this.permissionsService.loadPermissions(privileges, () => {

              observer.next(new LoginActions.LoginSuccessAction({user: res}));
              observer.complete();
            });
          });
    })
    .catch( (e:any)  => {
      return Observable.of(new LoginActions.LoginFailureAction(true));
    });

Upvotes: 2

Related Questions