使用 Ramda.js memoize 来缓存 angular2 http 调用

Using Ramda.js memoize in order to cache angular2 http calls

我正在尝试使用 Ramda 的 R.memoize 缓存一个 http 调用,如下所示:

@Injectable()
export class GeolocationService {

  private urls;
  private cachedAddressAutocomplete;

  constructor(private http: HttpClient) {
    this.urls = URLS;
    this.cachedAddressAutocomplete = R.memoize(input => {
      const body = 'address=' + input;
      return this.http.get(this.urls.GEOLOCATION.ADDRESS_AUTOCOMPLETE + body).map(res => res.json());
    });
  }

  addressAutocomplete(input: string) {
    return this.cachedAddressAutocomplete(input);
  }

  chooseAddress = (input$: Observable<string>): Observable<string> => {
    return input$
      .debounceTime(500)
      .distinctUntilChanged()
      .switchMap(input => input.length < 3 ? [] : this.addressAutocomplete(input));
  };

  addressFormatter = param => param.description;
}

来自我的调用组件:

@Component({
  templateUrl: './signup.component.html',
  providers: [FormStatusService]
})
export class SignupComponent implements OnInit {

  chooseAddress = this.geolocationService.chooseAddress;
  addressFormatter = this.geolocationService.addressFormatter;
  ...

chooseAddress 被 ng bootstrap 使用如下:

 <input type="text"
         formControlName="address"
         [ngbTypeahead]="chooseAddress"
         [inputFormatter]="addressFormatter"
         [resultFormatter]="addressFormatter"
         autocomplete="off"
         class="form-control"/>

但是,我在 chrome 控制台中注意到,即使输入与之前的输入相同,也会始终发出 http/ajax 调用。

有人可以帮忙吗?

我通过将我的 ramda-memoized 函数返回的 http observable 从 cold 转换为 hot 来实现预期的行为,如下所示:

@Injectable()
export class GeolocationService {

  private urls;
  private cachedAddressAutocomplete;

  constructor(private http: HttpClient) {
    this.urls = URLS;
    this.cachedAddressAutocomplete = R.memoize(input => {
      const body = 'address=' + input;
      return this.http.get(this.urls.GEOLOCATION.ADDRESS_AUTOCOMPLETE + body)
        .map(res => res.json())
        .publishLast().refCount();//http is hot now!
    });
  }

  addressAutocomplete(input: string) {
    return this.cachedAddressAutocomplete(input);
  }

  chooseAddress = (input$: Observable<string>): Observable<string> => {
    return input$
      .debounceTime(500)
      .distinctUntilChanged()
      .switchMap(input => input.length < 3 ? [] : this.addressAutocomplete(input));
  };

  addressFormatter = param => param.description;
}

默认情况下,angular2' http 返回的 observable 是冷的。请在此处查看 Thoughtram 博客 post:https://blog.thoughtram.io/angular/2016/06/16/cold-vs-hot-observables.html

通过使用 .publishLast().refCount(); 可以使 http Observable hot(而不是默认的 cold)。

现在当输入与上一个相同时,http 调用不会重新发出!

P.S。 如果您有任何建议或意见,请随时评论此答案。