Angular 2 - 可观察链和操作

时间:2017-06-29 14:37:21

标签: angular http rxjs observable

因此,我对角度以及一般的可观察性都很陌生。我知道如何处理承诺,但我希望对Observable方面更加满意。

我会尽量保持简短,但这是设置:

为了减少对服务器的调用量,我创建了一个包服务,它基本上将多个请求打包到一个请求中。

如果某个组件的缓存不是最新的,则会要求多个数据服务刷新其商店。需要服务器更新的每个数据服务都会向包添加请求。准备好后,组件将包发送到包服务,然后包服务将请求发送到服务器。

当服务器回复数据时,我需要每个数据服务使用与其单个请求相关的新数据更新其商店,然后通知组件所有内容都已完成。

这是我如何用承诺做到的:

1)组件从每个所需的数据服务构建一个包。

2)组件将其发送到返回promise的包服务。

3)包服务发送请求。

4)当服务器回复时,包服务会将响应分派给包中注册的每个数据服务。

5)只有当每个涉及的数据服务都更新其商店时,包服务才会解除其承诺。

6)该组件处理已解决/拒绝的承诺。

因此,尝试将此转换为可观察的模式,我得到了这个:

组件:

let thePackage = this.packageService.createPackageInstance();

this.service1.loadData( thePackage );
this.service2.loadData( thePackage );
this.packageService.sendPackage( thePackage ).subscribe( () => console.log("Success"), (err) => console.error( err ) );

Service1和Service2:

loadData( thePackage: Package ) {

    let needUpdate = this.GetCacheIsUpToDate();

    if( needUpdate ) {

        let params = { 
          "param1": true
        };

        //This would return a promise in a promise chain pattern.
        let callback = ( ( response:any ) => {

          //[...]
          //Do update the data store and notify subscribers.

          return Promise.resolve(); //The only way I know to make it work.
        });

        this.packageService.createRequest( thePackage, 100, 1, params, callback );
    }
}

PackageService:

createPackageInstance(): Package {

  return new Package({/* Some params */});
}


createRequest( thePackage:Package, theModule:number, operation:number, params:any, callback:Function ):void {

  let data = JSON.stringify( params );

  let request = new Request({
    "id":         Utils.generateGUID(),
    "theModule":  theModule,
    "operation":  operation,
    "data" :      data,
    "callback":   callback
  });

  thePackage.requests.push( request );
}


sendPackage( thePackage ): Observable<PackageResponse>{

  //Assume some variables like 'someUrl' to be setup
  //[...]

  let httpObs = this.http.post( someUrl, formData, someOptions ).map( response => {

    return response.json();
  });

  return httpObs.flatMap( ( response ) => {

     let pAll = [];
     thePackage.requests.forEach( request => {
         pAll.push( request.callback( response ) );
     });

     return Observable.fromPromise( Promise.all( pAll ) ); //This is really ugly
  });
}

编辑:编辑了一些代码,以显示我目前使用promises的版本。

1 个答案:

答案 0 :(得分:0)

很抱歉,如果这个答案不够完整 - 我没有太多时间去讨论太多细节,但是它太长了,不适合评论。

现在,您需要获取在callback中为来自服务器的每个数据定义的原始createRequest。对于基于承诺的解决方案,您应该采用类似的方法,对吗?但这不是太多Rx ......

我要做的是让createRequest返回服务可以订阅的可观察对象。在createRequest里面,这个可观察的引擎盖是Rx.BehaviorSubject:这是一个观察者也是一个观察者,所以每当你在它上面调用.next(message)时,该主题的下标将收到该消息。然后将此主题存储在包中。

然后,您不必在发出请求后调用回调,而是使用请求的相关数据调用刚存储的主题.next()。我之后立即调用.complete(),因此流被处理掉(假设我们不再接收该流,这似乎就是这种情况)

请记住,不鼓励使用Rx.BehaviourSubject,因为通常有更好的方法来处理这些情况,但在这种情况下我找不到更好的选择(可能有,但我'我不确定)