我正在编写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]))
)
)
答案 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