在map运算符内为null指定Observable引用不会产生任何影响

时间:2017-04-12 09:42:06

标签: angular angular2-services rxjs5 angular2-observables

我正在尝试使用hateoas实现创建通用DataService。 有一个REST api /root,它提供了所有hateoas链接。 例如,

{
    _links : {
        login : {
            href : '/login',
            method : 'POST'
        },
        orders : {
            href : '/orders',
            method : 'GET'
        },
        orderById : {
            href : '/order/{id}',
            method : 'GET'

        }
        .......
    }
}

在应用程序加载时,DataService应调用/root api并将响应存储在实例变量中,例如rootLinks。它应该适用于整个会话。

然后DataService应该提供followLinkByName方法,从可用的href获取rootLinks并触发新的http请求。

const rootUrl: string = '/root';
const baseUrl: string = 'http://localhost:8080';

@Injectable()
export class DataService {

  private observable$: Observable<any>;
  private rootLinks: any;

  constructor(private http: Http) {
    this.ngOnInit();
  }

  ngOnInit() {
    this.getRootLinks().subscribe();
  }

  private getRootLinks() {
    if (this.rootLinks) {
      return Observable.of(this.rootLinks);
    } else if (this.observable$) {
      return this.observable$;
    } else {
      this.observable$ = this.http.get(rootUrl).map(this.extractRootLinkData);
      return this.observable$;
    }
  }

  private extractRootLinkData(response: Response) {
    this.observable$ = null;                             // LINE 1
    let data = response.json();
    this.rootLinks = data._links;
  }


  private extractData(response: Response) {
    let body = response.json();
    return body;
  }



  followLinkByName(linkName: String): Observable<any> {
    let link;
    if (this.observable$) {                              // LINE 2
      return this.observable$.map((res) => {
        link = res._links[linkName];
        // make a http request and return the response
      });
    } else {
      link = this.rootLinks[options.linkName];
      options.link = link;
      // make a http request and return the response
    }
  }

}

我在DataService个提供程序数组中添加了此core module's, 并core module已导入app module

现在来自LoginComponent模块的pages使用此DataService登录。虽然在第1行中,observable$被指定为null,但是当从LoginComponent进行调用时,它在第2行可用。

快照, 1.在应用程序加载时,它调用/root api,一旦数据可用,将observable指定为null。 enter image description here

2.尝试登录时, enter image description here

1 个答案:

答案 0 :(得分:2)

由于this.http.get(rootUrl)来电是异步的,因此您确定在使用this时不会丢失.map(this.extractRootLinkData)上下文?

我认为当extractRootLinkData()方法被调用为map()的回调时,this上下文等于window。因此,您在this.observable$ = null上执行的语句window无论如何都不存在。

您可以改为使用匿名函数:

this.observable$ = this.http.get(rootUrl).map(response => this.extractRootLinkData(response));

...或绑定this上下文:

this.observable$ = this.http.get(rootUrl).map(this.extractRootLinkData.bind(this));

另见:How to access the correct `this` context inside a callback?