Muirik Muirik - 1 year ago 39
Javascript Question

Because Observable Subscription Happens on the Component, I'm Having Difficulty Refactoring Logic Into Service Layer on Angular 2 App

The one thing I'm finding in using observables in my Angular 2 app is that, because nothing actually "happens" until you subscribe to the observable in the component, that makes it a little tricky to refactor by moving logic into a service layer.

For instance, here is an example of a function that receives a sorting parameter, and then filters the data shown to the view accordingly. This uses an observable where subscription is happening in my components, like so:

onSortReceived(sort)
{
if (sort === 'alphabetical')
{
this.filtersService.getByFilter(this.page, this.pagesize, this.body)
.subscribe(resRecordsData => {
this.records = resRecordsData;
this.data = resRecordsData.data;
this.data.sort((a, b) => a.name.last.localeCompare(b.name.last));
},
responseRecordsError => this.errorMsg = responseRecordsError);
}
else if (sort === 'reverse alphabetical')
{
this.filtersService.getByFilter(this.page, this.pagesize, this.body)
.subscribe(resRecordsData => {
this.records = resRecordsData;
this.data = resRecordsData.data;
this.data.sort((a, b) => b.name.last.localeCompare(a.name.last));
},
responseRecordsError => this.errorMsg = responseRecordsError);
}
else if (sort === 'id')
{
this.filtersService.getByFilter(this.page, this.pagesize, this.body)
.subscribe(resRecordsData => {
this.records = resRecordsData;
this.data = resRecordsData.data;
this.data.sort((a, b) => b._id.localeCompare(a._id));
},
responseRecordsError => this.errorMsg = responseRecordsError);
}
else if (sort === 'reset') {
this.filtersService.getByFilter(this.page, this.pagesize, this.body)
.subscribe(resRecordsData => {
this.records = resRecordsData;
this.data = resRecordsData.data;
},
responseRecordsError => this.errorMsg = responseRecordsError);
}
}


Now, rather than have to repeat this code in each component that does this, I'd like to move much of this logic out to a service layer. But since the filtering is happening AFTER subscription, and subscription happens at the level of the component, I'm not sure how to do this. Is there a way I can filter first, and THEN subscribe to the observable? What would that look like? If I could do this I could move much of this code out to a service layer.

Answer Source

How about something like this:

filter: any;
onSortReceived(sort)
{
    if (sort === 'alphabetical')
    {
        filter = (a, b) => a.name.last.localeCompare(b.name.last);
    }
    else if (sort === 'reverse alphabetical')
    {
         filter = (a, b) => b.name.last.localeCompare(a.name.last);
    }
    else if (sort === 'id')
    {
            filter = (a, b) => b._id.localeCompare(a._id);
    }
    else if (sort === 'reset') 
    {
           filter = null;
    }

    this.filtersService.getByFilter(this.page, this.pagesize, this.body)
    .subscribe(resRecordsData => {
        this.records = resRecordsData;
        this.data = resRecordsData.data;
        this.data.sort(this.filter);
    },
    responseRecordsError => this.errorMsg = responseRecordsError);
}

Then you could more readily move the last block of code into a service as needed.

NOTE: This code was not syntax checked or tested.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download