代码之家  ›  专栏  ›  技术社区  ›  Florian Moser

在恢复之前等待RxJs.Subscription

  •  2
  • Florian Moser  · 技术社区  · 6 年前

    如何在恢复方法之前等待订阅完成?

    让我们有一个 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 回复  |  直到 6 年前
        1
  •  4
  •   Oles Savluk    6 年前

    如果你遵循“反应咒语”,你的问题就会得到解决:

    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>

    作为总结:

    • 整个应用程序订阅一次就足够了