0
votes

i have a code below.

loadAll$ = createEffect(() => {
    return this.action$.pipe(
        ofType(LOAD_ALL),
        switchMap(() => {
            
            const localDBCount = from(this.personDBService.countData())
            const localDBList = from(this.personDBService.getAll())
            const serviceList = this.personService.fetchAll();

            forkJoin([localDBCount, localDBList, serviceList]).pipe(
                map(results => {
                    if (results[0] > 0) {
                        //return the list
                        return LOAD_ALL_SUCCESS({ list: results[1] })
                    } else {
                        return LOAD_ALL_SUCCESS({ list: results[2] })
                    }
                })
            )

        }), catchError(err => {
            return of(LOAD_ALL_FAILED({ error: err }))
        })
    )
})

My Goal is when the LOAD_ALL action is called then in this effect method. It will check if there are some data or at least 1 data present in indexDB if there is then return the action LOAD_ALL_SUCCESS

else call the rest api then return the action LOAD_ALL_SUCCESS with the data got from the api

I'm getting an error on the switchMap which is expecting a return and I couldn't come up with a solution on this. I know formJoin joins the observables but not sure how to return a value.

Also all methods from the personDBService return Promises so i converted it to Observable using the from operator.

Error

Argument of type '() => void' is not assignable to parameter of type '(value: TypedAction<"[PERSON] Load All">, index: number) => ObservableInput'. Type 'void' is not assignable to type 'ObservableInput'.

21             switchMap(() => {
1

1 Answers

0
votes

You will need to return the forkJoin statement within the switchMap block, as the type signature of switchMap requires you to return an observable

loadAll$ = createEffect(() => {
    return this.action$.pipe(
        ofType(LOAD_ALL),
        switchMap(() => {
            
            const localDBCount = from(this.personDBService.countData())
            const localDBList = from(this.personDBService.getAll())
            const serviceList = this.personService.fetchAll();

            return forkJoin([localDBCount, localDBList, serviceList]).pipe(
                map(results => {
                    if (results[0] > 0) {
                        //return the list
                        return LOAD_ALL_SUCCESS({ list: results[1] })
                    } else {
                        return LOAD_ALL_SUCCESS({ list: results[2] })
                    }
                })
            )

        }), catchError(err => {
            return of(LOAD_ALL_FAILED({ error: err }))
        })
    )
});

Alternatively, a cleaner way of doing things would be to remove the use of nested pipes. This can be done by returning the observables from the forkJoin, and handle the returning of the respective actions down the primary pipeline through the map operator:

loadAll$ = createEffect(() => {
    return this.action$.pipe(
        ofType(LOAD_ALL),
        switchMap(() => {            
            const localDBCount = from(this.personDBService.countData())
            const localDBList = from(this.personDBService.getAll())
            const serviceList = this.personService.fetchAll();

            return forkJoin([localDBCount, localDBList, serviceList])
        }),
        map((results) => {
          if (results[0] > 0) {
                        //return the list
            return LOAD_ALL_SUCCESS({ list: results[1] })
          } else {
            return LOAD_ALL_SUCCESS({ list: results[2] })
          }
        }),            
    )
})