如何在 redux-observable 中处理异步函数? [英] How to handle async function in redux-observable?

查看:43
本文介绍了如何在 redux-observable 中处理异步函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 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.

它从不调用观察者的 obs.complete(),因此订阅可能会导致内存泄漏,因为它永远不会结束.

It never calls obs.complete() 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"
      observer.complete();
    };
    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-observable 中处理异步函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆