我一直在尝试创建一些cycle.js示例作为嵌套对话框,并使用选择框在它们之间切换。
其中一个对话是官方Github HTTP搜索示例的克隆。
另一个对话是一个更基本的对话,没有HTTP,只有DOM。
我觉得我把头转过来在2之间切换,但我对Rx很新,所以可能做得不正确或天真。
在我向搜索页面添加加载指示器之前,这一切似乎都运行良好。
为此,我转过身来:
const vTree$ = responses.HTTP
.filter(res$ => res$.request.indexOf(GITHUB_SEARCH_API) === 0)
.flatMapLatest(x => x)
.map(res => res.body.items)
.startWith([])
.map(results =>
h('div.wrapper', {}, [
h('label.label', {}, 'Search:'),
h('input.field', {type: 'text'}),
h('hr'),
h('section.search-results', {}, results.map(resultView)),
])
)
进入这个:
const searchResponse$ = responses.HTTP
.filter(res$ => res$.request.indexOf(GITHUB_SEARCH_API) === 0)
.flatMapLatest(x => x)
.map(res => res.body.items)
.startWith([])
const loading$ = searchRequest$.map(true).merge(searchResponse$.map(false))
// Convert the stream of HTTP responses to virtual DOM elements.
const vtree$ = loading$.withLatestFrom(searchResponse$, (loading, results) =>
h('div.wrapper', {}, [
h('label.label', {}, 'Search:'),
h('input.field', {type: 'text'}),
h('span', {}, loading ? 'Loading...' : 'Done'),
h('hr'),
h('section.search-results', {}, results.map(resultView)),
])
)
我现在有2个问题
感谢您的帮助!
编辑:解决了我自己的问题。见下面的答案。答案 0 :(得分:5)
我最终通过从头开始重建我的整个应用程序来解决这个问题,直到找到了断点。
我学到的是你需要将.share()
添加到任何可观察的流中,这些流将被多个下游的observable订阅/映射/等。
const searchRequest$ = DOM.select('.field').events('input')
.debounce(500)
.map(ev => ev.target.value.trim())
.filter(query => query.length > 0)
.map(q => GITHUB_SEARCH_API + encodeURI(q))
.share() //needed because multiple observables will subscribe
// Get search results from HTTP response.
const searchResponse$ = HTTP
.filter(res$ => res$ && res$.request.url.indexOf(GITHUB_SEARCH_API) === 0)
.flatMapLatest(x => x) //Needed because HTTP gives an Observable when you map it
.map(res => res.body.items)
.startWith([])
.share() //needed because multiple observables will subscribe
//loading indication. true if request is newer than response
const loading$ = searchRequest$.map(true).merge(searchResponse$.map(false))
.startWith(false)
.share()
//Combined state observable which triggers view updates
const state$ = Rx.Observable.combineLatest(searchResponse$, loading$,
(res, loading) => {
return {results: res, loading: loading}
})
//Generate HTML from the current state
const vtree$ = state$
.map(({results, loading}) =>
.........