在服务中共享同一个HTTP资源实例?

时间:2016-03-15 16:40:31

标签: angular rxjs

我有一个全局服务,旨在将单个引用分发给单个但可能正在更改的对象。通常情况下,我会通过" normal"组件的输入参数,但由于涉及路由器,这是不可能的。至少以下代码片段对我没有任何作用,甚至没有抛出错误:

<!-- All possible instances of this outlet have "project" set as input -->
<router-outlet [project]="project"></router-outlet>

因为我不能这样做(如果可以,请告诉我!),我创建了一个服务,我想用它来在所有请求者之间共享同一个实例。除此之外,如果我能够获得所有可观察到的新项目,如果需要不同的项目ID,我会很高兴。显然代码还没有这样做,因为它取代了整个缓存的Observable:

/**
* Wraps access to a whole project.
*/
@Injectable()
export class ProjectService {
    // The same instance should be shared among all projects
    private cache : {
        observable : Observable<Project>,
        id : string
    };

    /**
    * @param _http Dependently injected by Angular2
    */
    constructor(private _http: Http) { }

    /**
    * @param id The id of the project to retrieve
    * @return An observable that updates itself if the selected project changes.
    */
    getProject(id : string) : Observable<Project> {
        if (!this.cache || this.cache.id != id) {
            let obs = this._http.get('/api/project/' + id)
                .do(res => console.log(res.json()))
                .map(res => new Project(res.json()))
                .catch(this.handleError);

            this.cache = {
                observable : obs,
                id : id
            }
        }

        return this.cache.observable.share();
    }

    private handleError (error: Response) {
        // in a real world app, we may send the error to some remote logging infrastructure
        // instead of just logging it to the console
        console.error(error);
        return Observable.throw(error);
    }
}

我希望通过在observable上调用share()来避免后续的HTTP请求,但我想我错过了一些东西:目前我的应用程序发出一个新请求,每次调用getProject() ID。

我怎样才能获得服务:

  • 除非明确触发,否则不会在第一个之后执行任何后续HTTP请求?
  • 如果请求的ID更改,则使用新资源实例更新所有已订阅的Observable?

2 个答案:

答案 0 :(得分:1)

这应该做你想要的事情

getProject(id : string) : Observable<Project> {
    if (!this.cache || this.cache.id != id) {
        return this._http.get('/api/project/' + id)
            .do(res => console.log(res.json()))
            .map(res => new Project(res.json()))
            .map(res => return {
              observable : obs,
              id : id
             })
             .do(res => this.cache = res)
            .catch(this.handleError);
    } else {
      return Observable.of(this.cache);
    }
}

答案 1 :(得分:1)

我会更新您的服务:

getProject(id : string) : Observable<Project> {
  if (!this.cache || this.cache.id != id) {
    return this._http.get('/api/project/' + id)
         .map(res => new Project(res.json()))
         .do((data) => {
           if (!this.cache) {
             this.cache = {};
           }
           this.cache[id] = data;
         })
         .catch(this.handleError);
  } else {
    return Observable.of(this.cache[id]);
  }
}

如果要通知组件数据已更新,可以使用专用的observable。在设置缓存的同时,您可以使用关联的观察者触发事件......组件可以在observable上进行订阅以进行通知。