简体   繁体   English

如何使用 RXJS 动态链接函数调用?

[英]How to dynamically chain function calls using RXJS?

I need to cache the result of a request on the first call then read the cached value for subsequent calls.我需要在第一次调用时缓存请求的结果,然后为后续调用读取缓存的值。

To achieve that goal, I am using promises and I am chaining them.为了实现这个目标,我使用了 Promise 并将它们链接起来。 I have a working solution but I would like to convert it to RxJS's observables instead of Promises.我有一个可行的解决方案,但我想将其转换为 RxJS 的 observables 而不是 Promises。

Here is my working solution:这是我的工作解决方案:

private currentPromise: Promise<{ [key: string]: any }>;
private cache: any;
public getSomething(name: string): Promise<number>{
  return this.currentPromise = !this.currentPromise ? 
    this._getSomething(name) : 
    new Promise((r) => this.currentPromise.then(() => this._getSomething(name).then((res) => r(res))));
}

private _getSomething(name: string): Promise<any> {
  return new Promise((resolve) => {
    if (this.cache[name]) {
      this.messages.push("Resolved from cache");
        resolve(this.cache[name]);
      } else {
        // Fake http call. I would use Angular's Http class.
        setTimeout(()=> {this.messages.push("Resolved from server"); this.cache[name] = name; resolve(this.cache[name]); }, 2000 );
      }
  });
}

this.getSomething("thing1").then((res)=>this.messages.push(res));
this.getSomething("thing1").then((res)=>this.messages.push(res));
this.getSomething("thing2").then((res)=>this.messages.push(res));
this.getSomething("thing2").then((res)=>this.messages.push(res));
this.getSomething("thing1").then((res)=>this.messages.push(res));
this.getSomething("thing2").then((res)=>this.messages.push(res));
this.getSomething("thing1").then((res)=>this.messages.push(res));
this.getSomething("thing2").then((res)=>this.messages.push(res));

You can test it on this plunkr: https://plnkr.co/edit/j1pm2GeQf6oZwRvbUsXJ?p=preview您可以在此 plunkr 上对其进行测试: https ://plnkr.co/edit/j1pm2GeQf6oZwRvbUsXJ ? p = preview

How do I achieve the same thing with RxJS 5 beta?如何使用 RxJS 5 beta 实现相同的功能?

Update更新

Following Bergi's comments I updated my plunkr and my code to bring it closer to my real case根据 Bergi 的评论,我更新了我的 plunkr 和我的代码,使其更接近我的真实案例

AsyncSubjects are the Rx analog of Promises. AsyncSubjects是 Promises 的 Rx 模拟。 publishLast is the best way to turn an observable into one. publishLast是将 observable 转化为一个的最佳方式。 Something like this should work:这样的事情应该工作:

private cache: {string: Rx.Observable<any>};

public getSomethings(names: string[]) : Rx.Observable<any> {
    // call getSomething for each entry in names
    // streams is an array of observables
    const streams = names.map(name => this.getSomething(name));

    // transform streams into an observable with an array of results
    return Observable.zip(streams);
}

public getSomething(name: string) : Rx.Observable<any> {
    if (!this.cache[name]) {
        // create the request observable
        // const request = Rx.Observable.ajax(...); // http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-ajax
        // for now, just wait 2 seconds and return name
        const request = Rx.Obsevable.of(name).delay(2000);

        // use "do" to log whenever this raw request produces data
        const loggedRequest = request.do(v => this.messages.push("retrieved from server " + v));

        // create an observable that caches the result
        // in an asyncSubject
        const cachedRequest = loggedRequest.publishLast();

        // store this in our cache object
        this.cache[name] = cachedRequest;
    }

    // return the cached async subject
    return this.cache[name];
}


// usage
this.getSomething("thing1").subscribe(v => this.messages.push("received " + v));
this.getSomething("thing1").subscribe(v => this.messages.push("received " + v));
this.getSomething("thing1").subscribe(v => this.messages.push("received " + v));
this.getSomething("thing1").subscribe(v => this.messages.push("received " + v));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM