【问题标题】:How to Queue two observables?如何对两个 observables 进行排队?
【发布时间】:2017-05-11 15:53:37
【问题描述】:

我是 Angular 2 的新手。我的应用程序有一个配置文件,其中列出了所有 api url。

我创建了一个定位器服务来加载 config.json。其他服务使用此服务来获取其特定的 url。

@Injectable()
export class LocatorService {
    private config: any;
    private loadConfig: Promise<any>;
    constructor(private _http: Http) {
        this.loadConfig = this._http.get('config/config.json')
                .map(res => this.config = res.json()).toPromise();
    }

    public getConfig() {
        return this.loadConfig.then(() => this.config);
    }
}

我有这个向 url 发送 http 请求的其他服务。此服务从定位器服务获取 url。

@Injectable()
export class OtherService {
    private _data: any;
    private url: string;
    constructor(private _http: Http, private locatorService: LocatorService) {
      this.geturl();
    }

    public loadData(): model[] {
      this.geturl().then(() => this._http.get()
                  .map(res => this._data  = res.json())
                  .catch(error =>
                  Observable.throw(error.json().error || 'Server error'))
                  .subscribe(t => this._data = t.json());

       return this._data;
    }

    private geturl() {
        return this.locatorService.getConfig().then(t => {
        this.url = t.serviceUrl;
        console.log(this.url);
        });
    }
}

我的组件调用这个 loadData n 获取所需的数据。我如何达到同样的效果?

我不是很清楚如何等待配置 url 被加载然后发送 http 请求并返回数据。

请帮忙。

【问题讨论】:

  • 在这里使用 Promise 有什么意义?这两个请求实际上都是可观察的。你做错了什么,因为上面的代码应该导致顺序请求。请提供MCVE 以复制问题,请提供帮助。

标签: angular promise rxjs observable


【解决方案1】:

您不需要使用 Promise,因为这意味着 then 不需要使用您的 LocatorServicegetConfig 函数。进行如下更改,并确保您的应用程序中有 LocatorService 的单个实例并再次检查:

//定位服务

@Injectable()
export class LocatorService {
    private config: any = null;

    constructor(private _http: Http) {
        if (this.config === null ) {
          this._http.get('config/config.json')
              .map(res => res.json()).subscribe(res => {
                this.config = res;
              });
        }
    }

    public getConfig() {
        return this.config;
    }
}

//其他服务

@Injectable()
export class OtherService {
    private _data: any;
    private url: string;

    constructor(private _http: Http, private locatorService: LocatorService) {
      this.url = this.locatorService.getConfig();
    }

    public loadData(): model[] {
      return this._http.get(this.url.serviceUrl)
                  .map(res => this._data  = res.json())
                  .catch(error =>
                  Observable.throw(error.json().error || 'Server error'));         
    }

}

【讨论】:

  • 不,它不起作用。 getConfig 不等待 http 请求完成。
  • 上面的代码对原始代码没有任何好处。它并行运行请求,if (this.config === null ) 检查是无用的,因为构造函数每个服务实例只运行一次。
【解决方案2】:

你可以这样做:

@Injectable()
export class LocatorService {
    private loadConfig: Promise<any>;
    constructor(private _http: Http) {
        this.loadConfig = this._http.get('config/config.json')
                .map(res => this.config = res.json()).toPromise();
    }

    public getConfig() {
        return this.loadConfig;
    }
}

@Injectable()
export class OtherService {
    private _data: any;
    constructor(private _http: Http, private locatorService: LocatorService) {
    }

    public loadData() {
        Observable.from(this.locatorService.getConfig())
            .switchMap((config) => this._http.get(config.serviceUrl))
            .catch(error => Observable.throw(error.json().error || 'Server error'))
            .subscribe(t => this._data = t.json());
    }
}

【讨论】:

    猜你喜欢
    • 2018-03-24
    • 2020-10-06
    • 2016-02-20
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 2012-12-20
    • 2018-10-04
    相关资源
    最近更新 更多