我很难让某些时间flatMap
与Rx.DOM.getJson()
合作,并且无法弄清楚我做错了什么。
HTML
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"></script>
<script src="https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-xta1/t39.3284-6/12624096_747368668729465_1053913233_n.js"></script>
<script src="https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-xaf1/t39.3284-6/12624065_1518596455100766_427485197_n.js"></script>
<title>JS Bin</title>
</head>
<body>
<button id='fetch'>Fetch</button>
<div id="content"></div>
</body>
</html>
的javascript
// Actions
const Actions = {
LoadPosts: 'LoadPosts'
};
// Disptacher
const Dispatcher = new Rx.Subject();
function send(action) {
Dispatcher.onNext({action: action});
}
// Stores
const url = 'http://jsonplaceholder.typicode.com/posts';
const FetchedPosts$ = Dispatcher
.filter(x => Actions.LoadPosts === x.action)
.do(x => console.log(x))
.flatMap(() => {
console.log('flat');
return Rx.DOM.getJSON(url);
})
.do(x => console.log('after', x));
// Views
const fetchButton = document.getElementById('fetch');
const Fetch$ = Rx.Observable.fromEvent(fetchButton, 'click')
.do(x => send(Actions.LoadPosts));
const PostsView$
= FetchedPosts$.map(posts => posts.map(post => <li>{post.title}</li>));
const RootView$ = Rx.Observable.merge(Fetch$, PostsView$);
RootView$.subscribe(
content => ReactDOM.render(
<ul>{content}</ul>,
document.getElementById('content')
)
);
输出
[object Object] {
action: "LoadPosts"
}
"flat"
"Script error. (line 0)"
所以输出显示我进入平面地图,如果我拿出Rx.DOM.getJSON(url)
并订阅它,那么我可以写出返回的值。但是,在flatMap中没有任何内容返回,我在网络选项卡中看到一个错误,显示Rx正在取消请求,如下所示。
这是一个JsBin:http://jsbin.com/geruzo/edit?js,console,output
修改 我刚刚注意到,remove react允许Rx.DOM调用成功。
答案 0 :(得分:1)
好的,我将通过参考您的jsbin代码来回答,这与发布的代码不同,但我更容易检查。
首先,您可以在此处找到固定版本的代码: http://jsbin.com/yugener/edit?html,js,output
您的第一个问题是每次渲染都会触发“LoadPosts”操作,而不必单击按钮,这会导致无限的渲染循环。 Render-&GT; LoadPosts-&GT; Render-&GT; LoasPosts ...
// The send will just be executed when the component is rendered
<button click={send(Actions.LoadPosts)}>fetch</button>
它应该是(也是onClick,而不是点击):
<button onClick={() => send(Actions.LoadPosts)}>Fetch</button>
由于存在渲染循环,并且“LoadPosts”操作一直处于触发状态,因此在上一个请求完成之前再次调用Rx.DOM.getJSON,因此它将取消之前的请求。你不会抛出一个错误(请求中止等),并抓住它:
.flatMap(() => Rx.DOM.getJSON('http://jsonplaceholder.typicode.com/posts'))
.catch(error => console.log('error', error))
在RXJS中,catch操作符期望您返回一个observable,并且由于您没有,返回undefined,这反过来又引发了以下错误:
Uncaught TypeError: Cannot read property 'subscribe' of undefined
作为旁注,在您的情况下,不应使用flatMap,您应该使用switchMap(别名flatMapLatest),因为每次触发“LoadPosts”操作时,您都希望忽略所有先前的请求,并仅从最后一个获取数据请求。 有关两者之间差异的更多信息:flatMap vs switchMap。如果您可能希望通过设计中止先前的请求,flatMap也会避免出现“中止”错误,因为之前的observable不再发出值。