在继续之前等待RxJs.Subscription

时间:2018-10-12 11:40:05

标签: rxjs

如何恢复订阅才能等待订阅完成?

SettingService可以从服务器获取一次设置,然后将其缓存。它为其使用者提供了get(key): Setting方法,并确保仅存在具有相同键的设置的单个实例。这有两个含义:

  • 必须确保仅下载/缓存设置一次
  • 它必须处理消费者可能过早(在下载完成之前)请求服务的情况。

到目前为止我所拥有的:

export class SettingService {
    private settings: Setting[] = [];
    private settingSubscription: Subscription;
    private settingLoaded: Boolean = false;

    constructor(private http: HttpClient) {
        this.initSettings();
    }

    private initSettings() {
        this.settingSubscription = this.http.get<Setting[]>('api/Setting').subscribe(s => {
            this.settings = s;
            this.settingLoaded = true;
        });
    }

    get(key: string): Setting {
        if (!this.settingLoaded) {
            //TODO: wait for settingSubscription to finish
        }

        return this.resolveSetting(key);
    }

    private resolveSetting(key: String) {
        //uses this.settings to retreive the setting
    }
}

这个问题与Wait on RxJs.Subscriptions to finish before resuming非常相似,除了我必须确保异步方法只执行一次。

1 个答案:

答案 0 :(得分:4)

如果您遵循“反应性口头禅”,您的问题将得到解决:

Reactive mantra

请参阅The introduction to Reactive Programming you've been missing以了解其含义。

牢记这一想法,Settings服务可以按以下方式完成:

const { timer } = rxjs; // = require("rxjs")
const { map, mapTo, shareReplay } = rxjs.operators; // = require("rxjs/operators")

// emulate making ajax request
function loadSettings() {
  console.log('request to load settings ...');

  return timer(2000).pipe(
    mapTo({
      a: 'a-value',
      b: 'b-value'
    })
  );
}

// Settings service
const settings$ = loadSettings().pipe(
  shareReplay(1) // cache result
);
const get = key => settings$.pipe(
  map(s => s[key] || 'default')
);

// usage example
get('a').subscribe(v => console.log("result for a: ", v));
setTimeout(
  () => get('unknown').subscribe(v => console.log("result for unknown:", v)), 
  5000
);
<script src="https://unpkg.com/rxjs@6.3.3/bundles/rxjs.umd.min.js"></script>

回顾一下:

  • 将一切*保持为可观察状态
  • 整个应用1个订阅就足够