Sawtaytoes
9/30/2018 - 10:37 AM

Combining the Values of Merge-Mapped Observables

In this example, were able to emit actions as usual, but also wait for all merge-mapped observables to finish before getting all values submitted and emitting an action based on the result.

const ofPermissionType = (
  requiredPermissionType,
) => (
  filter(({ permissionType }) => (
    requiredPermissionType === permissionType 
  ))
)

const fetchPermissionsEpic = (
  action$,
  state$,
  { ajax },
) => (
  action$
  .pipe(
    ofType(FETCH_PERMISSIONS),
    map(props => ({
      ...props,
      accessToken: (
        accessTokenSelector(
          state$.value,
        )
      ),
    })),
    mergeMap(({
      accessToken,
      permissionTypes,
    }) => (
      from(permissionTypes)
      .pipe(
        map(permissionType => (
          of(permissionType)
          .pipe(
            takeUntil(
              action$
              .pipe(
                ofType(FETCH_PERMISSIONS),
                switchMap(({ permissionTypes }) => (
                  permissionTypes
                )),
                ofPermissionType(permissionType),
              )
            ),
            switchMap(() => (
              ajax({
                crossDomain: true,
                headers: {
                  'Authorization': `Bearer ${accessToken}`,
                },
                url: (
                  'https://example.com/permissions'
                  .concat('?')
                  .concat('permissionType=')
                  .concat(permissionType)
                ),
              })
              .pipe(
                pluck('response'),
                map(permissionValue => ({
                  permissionType,
                  permissionValue,
                })),
                map(storePermission),
                catchError(error => (
                  of(
                    caughtError(
                      error
                    )
                  )
                )),
              )
            )),
          )
        )),
        mergeAll(2),
        multicast(
          new Subject(),
          source$ => (
            source$
            .pipe(
              mergeOperator(
                source$
                .pipe(
                  toArray(),
                  map(finishedStoringPermissions),
                )
              ),
            )
          )
        )
      )
    )),
  )
)