RXJS error handling and wrapping multiple calls

91 views Asked by At

Is there a better way to orchestrate the below code in Rxjs ? and from Javascript perspective Promise/Asyc/Await which will be better considering some hard error and soft error handlings.

Couple of calls are hard dependency which are marked as hard true in the error and on subsequent error handler checks and re throw it. and soft errors are added to final data.error for any processing based on the soft errors.

How this can be better done ?


const { Observable } = require('rxjs');
const { map, filter, flatMap, concatMap } = require('rxjs/operators');

function testcallback(fail, callback) {
    if (fail == true) {
        setTimeout(function(){ callback(new Error({ message: "Operation failed" })); }, 100);       
    }
    else {
        setTimeout(function(){ callback(null, 10); }, 100);
    }
}

function createData(param) {
    return Observable.bindNodeCallback(testcallback)(param);
}

function associateData(param) {
    return Observable.bindNodeCallback(testcallback)(param);
}

function removeData(param) {
    return Observable.bindNodeCallback(testcallback)(param);
}

function markAssociateSuccess(param) {
   return Observable.bindNodeCallback(testcallback)(param);
}

function removeOldData(param) {
    return Observable.bindNodeCallback(testcallback)(param);
}

function getAllData() {
    return Observable.of( {error:null, data:[333]});
}


function updateData(updateData) {
    let param = updateRequest.param;
    return createData(1 == param)
        .catch((err) => {
            err.errorStep = 'CREATE_DATA';
            err.hard = true;
            throw (err);
        }).flatMap(
            () => {
                return associateData(2 == param)
                    .catch((err) => {
                        err.errorStep = 'ASSOCIATE_DATA';
                        err.hard = true;
                        return removeData(3==param)
                            .map(() => {
                                throw (err);
                            });
                    });
            },
            (createDataResponse, associateDataResponse) => {
                return [createDataResponse, associateDataResponse];
            }
        )
        .flatMap(() => {
             if (updateData.markAssociationSuccess) {
                return markAssociateSuccess(4 == param);
            } else {
                return Observable.of({});
            }
        }).catch((err) => {
            if (err.hard) {
                throw (err);
            }
            err.errorStep = 'ASSOCIATE_SUCCESS';
            return Observable.of({ error: err });
        })
        .flatMap((data) => {

            if (data.error) {
                return Observable.of(data);
            }
            return removeOldData(5 == param);
        }).catch((err) => {
            if (err.hard) {
                throw (err);
            }
            err.errorStep = 'REMOVE_OLD_DATA';
            return Observable.of({ error: err });
        })
        .flatMap(
            function fetchData() {
                return getAllData();
            },
            function resultSelector(prevRes, { error, data }) {
                if (error) {
                    return {};
                }
                if (prevRes.error) {
                    data.error = prevRes.error;
                }
                return data;
            }
        )
        .subscribe(
            function onNext(data) {
                console.log("Successful operation final data: " + data);
            },
            function onError(err) {
                console.log("Errored out" + JSON.stringify(err));
            },
            function onComplete() {
                console.log("Stream got completed");
            }
        );
}

const updateRequest = {
    param:1,
    markAssociationSuccess: true
}

updateData(updateRequest);
0

There are 0 answers