Steve Barthelot
Steve Barthelot

Reputation: 127

NgRx: get 'You provided 'undefined' where a stream was expected.' when calling complete action in effect

I am trying to do an API call and merge the existing data with existing data (the merge is done in addMissingData). I am getting an error when i try to call the :

Uncaught TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

at subscribeTo (subscribeTo.js:27) at subscribeToResult (subscribeToResult.js:11) at MergeMapSubscriber._innerSub (mergeMap.js:59) at MergeMapSubscriber._tryNext (mergeMap.js:53) at MergeMapSubscriber._next (mergeMap.js:36) at MergeMapSubscriber.next (Subscriber.js:49) at MapSubscriber._next (map.js:35) at MapSubscriber.next (Subscriber.js:49) at CatchSubscriber._next (Subscriber.js:72) at CatchSubscriber.next (Subscriber.js:49)

 GetStepWiseMasterData$ = createEffect(() => this.actions$.pipe(
            ofType(MasterDataAction.getCustomerMasterData),
            switchMap((action) => {
                return this.dataService.GetDataAsync(action.stepEnum).pipe(
                    map((response) => {
                        return {
                            isSuccess: response.isSuccess,
                            newData: response.data,
                            data: action.data,
                        };
                    }),
                    mergeMap((response) => {
                        if (response.isSuccess) {
                            this.addMissingData(response.newData, action.data).then(result => {
                                return [DataAction.getCustomerDataComplete({ customerData: result })];
                            });
                        } else {
                            return [DataAction.getCustomerDataFailed({ customerData: {} })];
                        }
                    }),
                    catchError(() => EMPTY)
                );
            })
        ));

   async addMissingData(newMasterData: BusinessPartnerMasterDataVM, existingMasterData: BusinessPartnerMasterDataVM = {}): Promise<any> {
        const omitNullValues = masterDataObj => new Promise((resolve) => {
            // filter with property name and delete all properties that are null
            Object.keys(masterDataObj).filter(propertyName => masterDataObj[propertyName] === null).forEach(propertyName => delete(masterDataObj[propertyName]));
            resolve(masterDataObj);
        });
        const masterNew = await omitNullValues(newMasterData);
        const masterOld = await omitNullValues(existingMasterData);
        const ret = Object.assign({}, masterNew, masterOld);
        return ret;
    }

Upvotes: 4

Views: 816

Answers (1)

Chathuranga Basnayake
Chathuranga Basnayake

Reputation: 144

Seem like your issue occurs in this area,

mergeMap((response) => {
    if (response.isSuccess) {
        this.addMissingData(response.newData, action.data).then(result => {
            return [DataAction.getCustomerDataComplete({ customerData: result })];
        });
    } else {
        return [DataAction.getCustomerDataFailed({ customerData: {} })];
    }
})

In here there's nothing return in the if (response.isSuccess) conditional branch. As I understand, you want to call two APIs which are

  1. First call getCustomerMasterData
  2. Then using the result of getCustomerMasterData, you want to call addMissingData

What I suggest is create another function to call above apis and then use the pipe.

GetStepWiseMasterData$ = createEffect(() => this.actions$.pipe(
    ofType(MasterDataAction.getCustomerMasterData),
    switchMap((action) => {
        return from(this.combinedFunction(action)).pipe(
            map((result) => {
                return { masterData: result };
            }),
            switchMap((result) => {
                return [MasterDataAction.getCustomerDataComplete(result)];
            })
        );
    })
));

async combinedFunction(action) {
    const response = await this.dataService.GetDataAsync(action.stepEnum).toPromise();
    if (!response.isSuccess) {
        return {};
    }
    return await this.addMissingData(response.newData, action.data);
}

from is required to convert the Promise to Observable which can import from rxjs, or you can modify the combinedFunction to return an Observable.

Hope this helped :)

Upvotes: 2

Related Questions