我有一个基本上采用DOM元素的函数,查找一些识别内容,并且(理论上)返回一个Observable
,其中包含上述标识内容withLatestFrom
和其他一些内容
我的问题是,返回的Observable
不会发出任何问题,即使它是由primaries$
和highlights$
可观察到的。{/ p>
如果解释得不好,我非常抱歉,我是ReactiveX / RxJS的新手,我正在尽我所能;如果您需要更多信息,请询问。
function randomFunction(element) {
// Create an observable sequence of text nodes from an array
const textNodes$ = Rx.Observable.from(getAllTextNodesFrom(element))
// Get "highlights" by doing stuff with text nodes
const highlights$ = textNodes$
.map(doSomeStuff)
.zip(textNodes$, (res, node) => ({res, node}))
.filter(({res, node}) => res.length && node.isConnected)
// Get "primaries" by doing stuff with "highlights"
const primaries$ = highlights$
.map(x => x.res)
.flatMap(x => x.filter(y => y.matches && y.isPrimary))
.map(x => x.id)
.toSet()
// Create return observable from highlights and primaries
const ret$ = highlights$.withLatestFrom(primaries$)
// These work
primaries$.subscribe(x => { console.log("primaries:", x) })
highlights$.subscribe(x => { console.log("highlights:", x) })
// This gives me nothing
ret$.subscribe(x => { console.log("return:", x) })
return ret$
}
谢谢!
答案 0 :(得分:1)
我观察到你使用了两次observable,在这种情况下你可能share
这些常见的源可观察。例如,highlights$
将订阅两次,一次为ret
生成值,一次生成primaries
的值。
除此之外,您还可以使用do
或tap
运算符进行日志记录,这将在不影响流的情况下执行日志记录副作用。您确实需要一个subscribe
来启动数据流。当您订阅ret
时,它会订阅highlight
和primaries
并上订阅链。
最后一句话,Rxjs中的多个订阅都很棘手。你需要意识到热与冷的二分法才能理解会发生什么。您可以找到详细检查内部工作here。
类似于:
function randomFunction(element) {
// Create an observable sequence of text nodes from an array
const textNodes$ = Rx.Observable.from(getAllTextNodesFrom(element))
// Get "highlights" by doing stuff with text nodes
const highlights$ = textNodes$
.map(doSomeStuff)
.zip(textNodes$, (res, node) => ({res, node}))
.filter(({res, node}) => res.length && node.isConnected)
.share()
.tap(console.log.bind(console, 'highlights:'))
// Get "primaries" by doing stuff with "highlights"
const primaries$ = highlights$
.map(x => x.res)
.flatMap(x => x.filter(y => y.matches && y.isPrimary))
.map(x => x.id)
.toSet()
.tap(console.log.bind(console, 'primaries:'))
// Create return observable from highlights and primaries
const ret$ = highlights$.withLatestFrom(primaries$)
// These work
ret$.subscribe(x => { console.log("return:", x) })
return ret$
}
答案 1 :(得分:0)
Building on what user3743222 said in their answer, turns out I also needed to pause/buffer highlights$
when creating ret$
, and wait for primaries$
to emit something before continuing. Here's how I did that using Rx.Observable.prototype.pausableBuffered
function randomFunction(element) {
// Create an observable sequence of text nodes from an array
const textNodes$ = Rx.Observable.from(getAllTextNodesFrom(element))
// Get "highlights" by doing stuff with text nodes
const highlights$ = textNodes$
.map(doSomeStuff)
.zip(textNodes$, (res, node) => ({res, node}))
.filter(({res, node}) => res.length && node.isConnected)
.share()
.tap(console.log.bind(console, 'highlights:'))
// Get "primaries" by doing stuff with "highlights"
const primaries$ = highlights$
.map(x => x.res)
.flatMap(x => x.filter(y => y.matches && y.isPrimary))
.map(x => x.id)
.toSet()
.tap(console.log.bind(console, 'primaries:'))
// Observable that outputs true when primaries$ outputs anything
const primariesExist$ = primaries$.map(() => true)
// Create return observable from highlights and primaries
return highlights$
.pausableBuffered(primariesExist$)
.withLatestFrom(primaries$)
}