我正在使用 RxJS 和 redux-observable.
I am using RxJS and redux-observable.
我正在尝试读取史诗中的文件.在我的情况下,我必须在史诗中做到这一点,因为其他一些史诗通过 expand 运算符触发了这个史诗多次未知".
I am trying to read file in epic. In my case, I have to do it in epic, because some other epic trigger this epic multiple "unknown" times by expand operator.
但由于 FileReader 是异步的,下面的代码不起作用.
But since FileReader is async, the code below does not work.
处理这个问题的正确方法是什么,尤其是 RxJS 方法?谢谢
What is the correct way especially RxJS way to handle this? Thanks
export const uploadAttachmentEpic = (action$, store) => action$ .ofType(UPLOAD_ATTACHMENT) .map(action => { const reader = new FileReader(); reader.onload = () => { return { ...action, payload: { ...action.payload, base64: reader.result } } }; reader.readAsDataURL(action.payload.file); }) .mergeMap(action => ajax .post( /* use action.payload.base64 */ ) .map(uploadAttachmentSucceed) .catch(uploadAttachmentFailed) ); 推荐答案Fan 的回答(在撰写本文时)很好,但有一些重要的警告:
Fan's answer (as of this writing) is good but has some caveats to it that are important:
它立即开始读取文件,而不是延迟读取.所以只要调用 readFile(file) 就可以在任何人订阅之前启动它.这很容易出错,因为有人可能不会立即同步订阅它,然后 reader.onload 会错过它.理想情况下,可观察对象是完全惰性且可重复的工厂.
It starts reading the file immediately instead of lazily. So just calling readFile(file) starts it even before anyone has subscribed. This is error-prone because it's possible that someone might not synchronously subscribe to it right away and then the reader.onload will miss it. Observables are ideally made completely lazy and repeatable factories.
它从不调用观察者的 obsplete(),因此订阅可能会导致内存泄漏,因为它永远不会结束.
It never calls obsplete() on the observer, so it's possible the subscription will be a memory leak because it never ends.
观察者上的方法没有绑定,所以 reader.onerror = obs.error 实际上不会工作.相反,您需要 e =>obs.error(e) 或 obs.error.bind(obs) 请参阅此处以了解原因
The methods on the observer are not bound, so reader.onerror = obs.error won't actually work. Instead you need to either e => obs.error(e) or obs.error.bind(obs) See here for reference on why
它不会在取消订阅时中止阅读.
It doesn't abort the reading on unsubscribe.
我会这样做:
function readFile(file){ // Could use Observable.create (same thing) but I // prefer this one because Observable.create is // not part of the TC39 proposal return new Observable(observer => { const reader = new FileReader(); reader.onload = (e) => { observer.next(reader.result); // It's important to complete() otherwise this // subscription might get leaked because it // "never ends" observerplete(); }; reader.onerror = e => observer.error(e); reader.readAsDataURL(file); // unsubscribe handler aka cleanup return () => { // LOADING state. // Calling abort() any other time // will throw an exception. if (reader.readyState === 1) { reader.abort(); } }; }); }这种模式几乎可以应用于任何 API,因此了解其工作原理非常方便.
This pattern can be applied to nearly any API, so it's pretty handy to understand exactly how it works.
我希望范不介意批评!我无意冒犯,只是想分享知识.
I hope Fan doesn't mind the critique! I don't mean to offend, just want to share knowledge.
更多推荐
如何在 redux
发布评论