服务http.get调用完成后有组件执行功能

时间:2016-01-12 14:00:19

标签: angular asynchronous rxjs observable

我在使用angular2中的观察者和订阅时遇到了麻烦。我目前遇到的问题如下:

我有一个服务,其中包含从API发布和获取数据的方法。该服务被注入一个组件,该组件直接调用服务中的那些方法。然后,该服务检索数据并将其自身存储,但我想在组件中处理该数据。在服务检索并存储数据本身之后,我无法弄清楚如何让组件执行一个函数。

service.ts

import { Injectable } from 'angular2/core';    
import { Http } from 'angular2/router';

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        return this.http.get(url).subscribe(
            result => this.result = result.json(),
            error => console.log(error),
            () => {}
        )
    }
}

component.ts

import { Component } from 'angular2/core';
import { Service } from './service';

@Component({
    ...
})
export class Component {
    formattedResult: Object;

    constructor(service: Service) {
        this.service = service;
        this.service.httpGet('/api')

        // How do I call format result on service.result only after it is completed?
        this.formatResult(service.result) // Need to execute this after the http call is completed

        // I want something like:
        this.service.httpGet('/api').then(() => formatResult(this.service.result));
    }

    formatResult(result) {
        this.formattedResult = result.map(x => x.length) // For example
    }
}

4 个答案:

答案 0 :(得分:5)

回答我自己的问题:

在app root中,使用以下命令导入Rxjs:

import 'rxjs/Rx';

这使您可以访问完整的Observable对象(而不仅仅是Angular附带的' Observable-lite')。这使您能够.map .reduce等Http请求。

现在,您可以在Http请求上使用.map在服务上下文中执行任意代码,即使它是订阅结果的组件。因此,要实现我在开始时要做的事情,我们可以:

service.ts

import { Injectable } from 'angular2/core';    
import { Http } from 'angular2/router';

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        return this.http.get(url).map(
            result => {
                let data = result.json();
                this.result = data;
                return data
            }
        )
    }
}

component.ts

import { Component } from 'angular2/core';
import { Service } from './service';

@Component({
    // Component setup
})
export class Component {
    formattedResult: Object;

    constructor(service: Service) {
        this.service = service;
        this.service.httpGet('/api').subscribe(
            data => this.formatResult(data);
        );
    }

    formatResult(result) {
        this.formattedResult = result.map(x => x.length) // For example
    }
}

感谢Gunter和Mark的回复,帮助我绕过这一点,我觉得我更了解Observables,经历了很多解决这个问题的文档!

答案 1 :(得分:2)

检查结果是否已经到达,如果是,则创建一个新的保证并用结果完成,但不是,获取它,并将其作为保证返回。

@Injectable()
export class Service {
    result: Object;

    constructor(http: Http) {
        this.http = http;
    }

    httpGet(url) {
        if(result === undefined) {
          return this.http.get(url).toPromise().then(
              result => this.result = result.json(),
              error => console.log(error);
          );
        } else {
          return new Promise().resolve(result);
        }
    }
}

我不知道TS,这段代码可能包含一些错误(我只使用Angular Dart),但你应该明白这一点。

另见
- http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

答案 2 :(得分:0)

那么你可以使用回调函数,

举个例子 考虑这是post函数,它触发服务模块中的post服务

postData(id: string, name: string) {
    console.log("Got you",id);
  this._employeeService.postServices({id: id, name: name})
    .subscribe(
      (response:Response) => this.consoleMyOutput(),
      error => console.log(error)
    );  
}

这里注意函数consoleMyOutput()。 一旦在调用服务后获得响应,就会触发此操作

现在,

consoleMyOutput(){console.log("Write Your call back function")};

此功能将在此之后触发。

答案 3 :(得分:0)

只需使用Rxjs方法就可以实现,这里是在应用程序加载后调用服务的简单而经典的方法,然后我们可以将它订阅到多个组件中。 确保服务应该可以重用于所有组件,因此可以在服务和映射中执行代码,只在组件中进行订阅:

服务

 import { Injectable } from 'angular2/core';    
 import { Http } from 'angular2/http';

 @Injectable()
 export class Service {
     result: Object;

     constructor(private http: Http) {}

     private _urlGet = '/api';

     httpGet(){
        return this.http.get(this._urlGet)
          .map(res => JSON.parse(res.json()))
          .do(result => {
             this.result = result;
           }, error => console.log(error))
     }
  }

<强>组件

 export class Component {
    formattedResult: Object;

    constructor(private service: Service) { }

    ngOnInit(){
       this.service.httpGet().subscribe(result => {
          this.formattedResult = result;
       }
    }
 }