Created
January 30, 2016 11:21
-
-
Save pchi/5cca83868713c6bd60a6 to your computer and use it in GitHub Desktop.
chaining observables with Rx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// watch angular scope $destroy expression and create a kill observable | |
var controllerScopeIsDestroyed = angularObservableSvc.watchToObservable($scope, '$destroy'); | |
// get datamart status request | |
var statusObs = dataMartSvc.getSavedState({ | |
userId: $stateParams.id, | |
refId: $stateParams.ref | |
}); | |
// get custom views request | |
var getCustomViewsObs = dataMartSvc.getCustomViews(); | |
// generic service | |
var service = { | |
// status = statusObs, views = getCustomViewsObs | |
setupDMwithCustomViews(status, views) { | |
var customViews = utilities.mapCdaResponse(views.data); | |
var viewsCollection = customViews ? [customViews] : []; | |
var dataMart = _.extend(status, {customViews: viewsCollection}); | |
return dataMart; | |
} | |
} | |
/* | |
* using zip to mimic concurrency since both responses have same CDA response structure. | |
* you can pass N number of observables with result selector method as the last argument. | |
* concatMap ensures order of results with our chained promises | |
* indentation shows an additional action/observable that is pushed into the sequence | |
* our sequence blueprint: | |
* | |
* zip ( status observable and custom views observable ) | |
* concat datamart preferences observable | |
* concat get count observable | |
* stream = [ [status, customViews], [preferences], [count] ] | |
* | |
* all the observables are flattened into one event stream which we then subscribe to | |
* onNext() will be fired when the final result is ready which renders our grid | |
*/ | |
var getGridDataSequence = Rx.Observable.zip(statusObs, getCustomViewsObs, service.setupDMwithCustomViews) | |
.concatMap((dataMart) => { | |
// Compute dataView properties based on profile and search criteria | |
var dataViewProperties = detailsGridSvc.getViewProperties(dataMart.profile, dataMart.searchCriteria); | |
// Get mart preferences and count and prepare Kendo grid for loading data | |
return dataMartSvc.getPreferences(dataMart.properties.tableName, dataMart.profile) | |
.concatMap((preferences) => { | |
var dataMartProperties = detailsGridSvc.createFiltersAndSorts(preferences, dataMart, dataViewProperties); | |
if (customViewsSvc.isCustomView(dataMart.profile)) { | |
dataMartProperties = customViewsSvc.getIntersectedFiltersAndSorts(dataMartProperties); | |
} | |
// Then get total row count | |
return detailsGridSvc.getCount(dataMartProperties.properties.tableId, dataMartProperties.filters) | |
.map((filterCount) => { | |
dataMartProperties.filterCount = filterCount; | |
return dataMartProperties; | |
}) | |
.retry(3); // count request is unstable, try 3x | |
} | |
}) | |
.takeUntil(controllerScopeIsDestroyed) // kill async sequence when controller is destroyed | |
.take(1); // just run it once on INIT | |
getGridDataSequence.subscribe({ | |
onNext(dataMart) { | |
var dataSource = detailsGridSvc.createKendoGridHybridDataSource(AppSettings.pentaho.queryPath, dataMart); | |
// send dataMart properties and dataSource to create Grid | |
detailsGridSvc.createGrid(dataMart, dataSource); | |
}, | |
onError(err) { | |
spinnerSvc.stop('spinner-details-container'); | |
}, | |
onCompleted() { | |
// update scope model to fire digest cycle and show grid | |
$scope.isReady = true; | |
} | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment