angularngrx

How to handle asynchronous operations with in an NgRx Effect?


I have an ngrx effect function that initially looks like


importItems$ = createEffect(() => this.actions$.pipe(
    ofType(ItemActions.loadItems),
    mergeMap(() => this.itemService.getItems().pipe(      
      map((_) => {
           let validItems:any
            let invalidItems:any
        var helper = new Helper()
        // async operations
        validItems = helper.loadValidItems().then((res) => validitem = res)
        invalidItems = helper.loadInalidItems().then((res) => invaliditem = res)
        // save to reducer
        return ItemActions.loadItemsSuccess({validItems,invalidItems})

      })
    ))
  ));
}

the problem is that

helper 

operations are async, it needs to search a xlsx file which takes time.

The problem is that if i run this code, i get:

     return ItemActions.loadItemsSuccess({validItems,invalidItems})

with

null 

values, because

  validItems = helper.loadValidItems().then((res) => validitem = res)
        invalidItems = helper.loadInalidItems().then((res) => invaliditem = res)

take some time and are finished after return functions. So i used Promise all

     Promise.all([
                validItems = helper.loadValidItems().then((res) => validitem = res)
        invalidItems = helper.loadInalidItems().then((res) => invaliditem = res)
        ]).then(() => {
            return ItemActions.loadItemsSuccess({validItems,invalidItems})
        })

but now it doesnt work. How to solve this problem?

I figured out, that there cant be return function inside promise all method, but i need somehow to wait for two async operations to end, then take their data, and then set them in reducer.


Solution

  • promises aren't handled in a correct way.

    fixed version:

    importItems$ = createEffect(() => this.actions$.pipe(
        ofType(ItemActions.loadItems),
        mergeMap(() => this.itemService.getItems()) // result is unused. idk why it is in the code
        mergeMap((items) => forkJoin({ // forkJoin will make sure event is emitted to the next operator when everything is complete
          validItems: helper.loadValidItems(),
          invalidItems: helper.loadInalidItems()
        })),
        map((data) => ItemActions.loadItemsSuccess(data))
      ));