如何在rxjs 6中将“静态”可观察的与“动态”合并?

时间:2018-09-11 08:17:44

标签: typescript google-chrome-extension rxjs rxjs6

我正在编写chrome扩展程序,并决定将所有内容包装到流中,主要用于培训并研究rxjs。

所以我陷入了这样的问题。我有两个流,一个是 static (不知道如何正确命名),另一个是 动态

静态流是仅当您订阅它( getPath $ )时才发出值的流,它从chrome存储中返回值。 动态( message $ )流是侦听事件(消息)的流。

所以我的目标是以某种方式合并这两个流,并且每当我收到来自 message $ 的消息时,便从 getPath $ 获得价值并进行一些计算基于两个值。

type Handler = (
    message: any, 
    sender: any, 
    sendResponse: (response: any) => void
) => void; 

type Values  = string | string[];

const getValues = (values: Values) => (cb) => chrome.storage.local.get(values, cb) 
const getPathBinded = bindCallback(getValues('path')) 
const getPath$ = getPathBinded() 

const message$ = fromEventPattern( 
   (handler: Handler) => chrome.runtime.onMessage.addListener(handler), 
   (handler: Handler) => chrome.runtime.onMessage.removeListener(handler), 
   (message, sender, sendResponse) => ({ message, sender, sendResponse }) 
).pipe( 
    map(
       ({ message }) => message
    ) 
) 

我发现了如何以这种方式做到这一点:

message$.pipe( 
    switchMap( 
        _ => getPath$, 
        (oV, iV) => {
            //doing some calculation
        } 
    ) 
 )

combineLatest(
  message$,
  getPath$,
).pipe(
    map((a, b) => {
       //doing some calculation
    })
)

似乎正在运行,但感觉好像我做错了。有什么建议或如何遵循最佳方法吗?另外,请在定义中纠正我。

UPD 这里是完整的code: https://gist.github.com/ 以及最新的有效版本

const merged$ = message$.pipe(
   switchMap(sendedPath => combineLatest(
        path$,
        unit$
    ).pipe(
        map(([path, unit]) => [sendedPath, path, unit]))
    )
)

2 个答案:

答案 0 :(得分:1)

如果您的目标是

  

合并这两个流,并且每当我收到来自   message $从getPath $获取值,并基于两个值进行一些计算

看来/usr/local/lib/python3.6/site-packages/ethereum/utils.py方法是正确的方法。 switchMap在这种情况下是指:每当我收到来自switchMap的通知时,我都会切换到另一个Observable,在这种情况下,是通过调用message$返回的。

如果您想同时使用这两个值,那么您可能无法忽略getPath$所通知的值(这是您的代码当前执行的操作),因此您必须使用管道{{1} }放入message$的结果中,这样您就可以创建一个包含2个Observable通知的2个值的对象,并将该对象传递给以下计算。代码应该像

map

答案 1 :(得分:1)

您所称的动态/静态与Hot and Cold Observables类似,但不完全相同。

您最好使用switchMap的第一种方法,只是每次都应重新计算它:

const combined$ = messages$.pipe(
  mergeMap(() => getPathBinded(), (message, path) => { ... })
)

我也将switchMap更改为mergeMap,否则,您可能会“丢失”一些消息,请参阅RxJS: Avoiding switchMap-Related Bugs


您也可以稍微简化一下代码:

const getStorage = bindCallback(chrome.storage.local.get); 
// use it as: const path$ = getStorage("path")

const message$ = fromEvent(chrome.runtime.onMessage);    
// should be enough, since you are only using default methods