noor noor - 10 days ago 4
Javascript Question

Set global variable of class from inside a promise Angular 2

I am facing a weird issue in assigning response to a class's global variable from inside a observable. So my program logic is as follows:


  1. Get latest playlists ID's from elastic search (i use elastic search from a type definition file). This returns me a PromiseLike to which i hook a then operator.

  2. Inside the promise resolution, i make another http get call (i.e an observable)

  3. In Observable subscription, i assign my global array with the response from the server.



Code is working correctly, I am getting responses as they should be but i cant assign the variable to the global one.

Here is my code:

import {Component, OnInit} from '@angular/core';
import {PlaylistService} from '../api/services'

@Component({
selector: 'app-playlists',
templateUrl: './playlists.component.html',
styleUrls: ['./playlists.component.css']
})
export class PlaylistsComponent implements OnInit {
public playlists: any[] = [];

constructor(private playlistService: PlaylistService) {

}

ngOnInit() {
let that = this;
this.playlistService.listIds().then((val) => { // <-- promise resolution
return this.playlistService.getByIds(val).toPromise(); // <-- http get call which i then convert to promise for simplicity
}).then((res) => { // <-- resolution of the http get call
console.log(this.playlists); <-- in this log, i get my desired results
// here is my problem, this assignment doesn't happens
this.playlists = res.data;
});
}
}


The listIds function is as follows:

listIds() {
return this.api.listing('playlist').then((body) => {
let hits = body.hits.hits;
return _.keys(_.groupBy(hits, '_id'));
});
}


and here is my api.listing function (elastic search client)

listing(type: string) {
let es = this.prepareES();
return es.search({
index: 'test',
_source: ["_id"],
type: type
});
}


The return type of es.search is


search(params: SearchParams): PromiseLike>;


Any ideas why i am not being able to assign value to global variable?

Answer

It looks like the promise returned by this.playlistservice.listIds() doesn't run inside Angulars zone. This is why Angular2 doesn't run change detection and doesn't recognize the change.

You can invoke change detection explicitly after the change:

 constructor(private playlistService: PlaylistService, private cdRef:ChangeDetectorRef) {

...

   ngOnInit() {
        let that = this;
        this.playlistService.listIds().then((val) => { // <-- promise resolution
            return this.playlistService.getByIds(val).toPromise(); // <-- http get call which i then convert to promise for simplicity
        }).then((res) => {  // <-- resolution of the http get call
            console.log(this.playlists); <-- in this log, i get my desired results
            // here is my problem, this assignment doesn't happens
            this.playlists = res.data; 
            this.cdRef.detectChanges(); 
        });
    }
Comments