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

Javascript 如何使用RXJS动态链接函数调用?,javascript,typescript,promise,rxjs,rxjs5,Javascript,Typescript,Promise,Rxjs,Rxjs5,我需要缓存第一次调用的请求结果,然后读取后续调用的缓存值 为了实现这一目标,我使用承诺,并将其链接起来。我有一个可行的解决方案,但我想将其转换为RxJS的可观测值,而不是承诺 以下是我的工作解决方案: private currentPromise: Promise<{ [key: string]: any }>; private cache: any; public getSomething(name: string): Promise<number>{ return

我需要缓存第一次调用的请求结果,然后读取后续调用的缓存值

为了实现这一目标,我使用承诺,并将其链接起来。我有一个可行的解决方案,但我想将其转换为RxJS的可观测值,而不是承诺

以下是我的工作解决方案:

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));
私人承诺:承诺;
私有缓存:任意;
public getSomething(名称:string):承诺{
返回this.currentPromise=!this.currentPromise?
这个。_getSomething(名称):
新承诺((r)=>this.currentPromise.then(()=>this;
}
private\u getSomething(名称:string):承诺

如何使用RxJS 5 beta版实现同样的效果

更新

根据Bergi的评论,我更新了我的plunkr和我的代码,使其更接近我的真实情况

是承诺的Rx模拟。是将可观察到的事物转化为可观察事物的最佳方式。像这样的方法应该会奏效:

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));
私有缓存:{string:Rx.Observable};
publicGetSomeThings(名称:string[]):Rx.Observable{
//为名称中的每个条目调用getSomething
//“流”是一组可观测数据
const streams=names.map(name=>this.getSomething(name));
//将流转换为具有一系列结果的可观察流
返回可观察的.zip(流);
}
public getSomething(名称:string):Rx.Observable{
如果(!this.cache[name]){
//创建可观察的请求
//const request=Rx.Observable.ajax(…);//http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#静态方法ajax
//现在,只需等待2秒钟并返回name
const request=Rx.Obsevable.of(name).delay(2000);
//每当此原始请求生成数据时,使用“do”进行日志记录
const loggedRequest=request.do(v=>this.messages.push(“从服务器检索”+v));
//创建缓存结果的可观察对象
//在一个主题中
const cachedRequest=loggedRequest.publishLast();
//将其存储在缓存对象中
this.cache[name]=cachedRequest;
}
//返回缓存的异步主题
返回此.cache[name];
}
//用法
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));

新承诺((r)=>这个.currentPromise.then(()=>这个._getSomething(params.then((res)=>r(res)));
”-什么?这应该做什么(和:)?为什么不直接返回
currentPromise
?如果已经在缓存
currentPromise
,则无需在
.cache
中额外缓存值本身。不要过于复杂。@Bergi每次调用“getSomething”时,我都会在currentPromise中添加一个新的“.then()”,这样所有“getSomething”调用都会按照调用顺序执行。第一个调用从服务器获取数据并缓存它。后续调用从缓存返回数据。您不需要多次执行它们-您已经在
currentPromise
中获得了第一次调用的结果(promise for The)。您只需将其返回多次即可。它将以隐式附加的相同顺序调用所有回调。在我的现实世界中,_getSomething每次都必须被调用,因为“params”可以更改结果。我的缓存实际上是一个字典。因此,如果我调用getSomething(“thing1”),它将检查“thing1”是否已经在缓存中,如果没有,它将调用服务器。谢谢,这非常有用。我知道我的问题中没有包括这一点,但您如何处理“getSomething”可以接收一组要进入参数的内容的情况。示例:getSomething([“thing1”,“things2”])将从服务器上同时获取这两个内容,然后getSomething([“thing1”,“thing3”])将从缓存中返回thing1,从服务器返回thing3。您希望可观察对象生成什么?一系列的结果?没错。我不确定它将如何工作,但我猜它将使用next()来聚合数组中的“东西”,然后在订阅者准备就绪时调用complete()函数来触发订阅者。我添加了一个
getSomethings
,它显示了如何获取一个输入数组并返回一个可观察的对象,从而生成一个带有结果的数组。它对每个项目使用
getSomething
,因此您仍然可以获得缓存的好处。感谢您的更新。你的解决方案很有效,但对我的情况来说仍然不完美。服务器实际上接收字符串数组并返回“things”数组。示例:假设“thing1”和“thing2”是缓存的。然后我调用getSomethings([“thing1”、“thing2”、“thing3”、“thing4”),它必须将[“thing3”、“thing4”]发送到服务器,等待响应,然后将缓存中的[“thing1”、“thing2”]与服务器中的[“thing3”、“thing4”]合并。最后,我希望能够在应用程序启动时预装一些“东西”。