为每个事件类型创建一个可观察的事件,并在最后一次取消订阅时销毁

时间:2019-02-13 08:49:12

标签: rxjs reactive-programming

想象一个消息流,每个消息流都具有关联的用户ID。对于收到的每条消息,获取相关的用户信息(可观察到“用户获取”)。这些用户获取的可观察对象将保持活动状态,并监视目标用户将来的任何更改。

问题:

  1. 如何防止为给定的用户ID创建重复的“用户获取”可观察对象(并重用可能已经创建的可观察对象)?
  2. 如何正确清除所有用户获取的可观察对象以取消订阅和/或完成操作?

我在哪里:

  1. 我无法确定现有的运算符或方法来防止出现可重复观察到的事物,因此我编写了类似于switchMap的运算符。我不喜欢在实践中该如何完成?

  2. 如果我能解决1,我相信纠正清理和重用的解决方案是refCount()

1 个答案:

答案 0 :(得分:1)

如果我正确理解了问题,则您有一个流发出id-s并基于该流事件,另一个流从远程位置(服务器)接收一些与ID相关的数据。

我建议的解决方案是创建一种store来保存缓存的数据,并在从id流中接收到一条消息后对其进行检查,并返回来自新请求或响应的响应。缓存的数据。

/** 
 * callBack end mocks an http request
 */
let callBackEnd$ = id => {
  customLog("___________________");
  customLog("Calling the server for " + id);
  customLog("___________________");

  return of({ id: id, data: `Some data about ${id}` });
};

/**
 * idStream$ mock the stream of id-s to be called trough http request
 */
let idStream$ = from([1, 2, 2, 3, 1, 5, 3, 4, 5]);

/**
 * We use reqStore$ to cache the already retrieved data
 */
let reqStore$ = new BehaviorSubject([]);

/**
 *  1. We subscribe to the message stream ( the stream that will tell us what to load )
 *
 *  2. With `latestFrom` we take the current store and check for any cached data, and return
 *  the cached data or the response of the new request
 *
 *  3. If the response of the `switchMap` doesn't exist in our store we add it.
 */
idStream$
  .pipe(
    tap(message => customLog(`Receiving command to retrieve : ${message}`)),
    withLatestFrom(reqStore$),
    switchMap(([e, store]) => {
      let elementSaved = store.find(x => x.id === e);
      return elementSaved ? of(elementSaved) : callBackEnd$(e);
    }),
    withLatestFrom(reqStore$),
    tap(([response, store]) => {
      if (!store.find(x => x.id === response.id)) {
        reqStore$.next([...store, response]);
      }
    })
  )
  .subscribe(([currentResponse, currentStore]) => {
    customLog("Receiving response for " + currentResponse.data);
  });

这里是Codesandbox的现场演示,希望对您有所帮助:)