繁体   English   中英

如何在redux-observable中处理异步功能?

[英]How to handle async function in redux-observable?

我正在使用RxJS和redux-observable。

我正在尝试读取史诗级的文件。 就我而言,我必须在史诗中执行此操作,因为其他一些史诗会由expand运算符多次触发该史诗。

但是由于FileReader是异步的,因此下面的代码不起作用。

特别是RxJS处理此问题的正确方法是什么? 谢谢

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)
    );

范的答案(截至撰写本文时)是好的,但有一些重要的警告事项:

  • 它立即开始读取文件,而不是懒惰地读取文件。 因此,即使在没有任何人订阅之前,只需调用readFile(file)启动它。 这很容易出错,因为有人可能没有立即同步订阅它,然后reader.onload会错过它。 理想情况下,可观察对象是完全懒惰且可重复的工厂。

  • 它永远不会在观察者上调用obs.complete() ,因此预订可能会因为obs.complete()而导致内存泄漏。

  • 观察者上的方法reader.onerror = obs.error ,因此reader.onerror = obs.error实际上不会起作用。 相反,您需要e => obs.error(e)obs.error.bind(obs) 请参阅此处以获取有关为什么的参考

  • 它不会终止退订时的读取。

这是我的处理方式:

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,因此很容易了解确切的工作方式。


我希望范不介意批评! 我并不是要冒犯,只是想分享知识。

您的文件读取过程确实返回了一个Observable。 异步过程未正确处理。 我建议创建一个文件读取函数,该函数首先返回一个可观察的对象。 然后将其附加到flipMap()

  function readFile(file){
    let reader = new FileReader();
      return Observable.create(obs => {
        reader.onload = function (e) {
            obs.next(reader.result);
        };
        reader.onerror = obs.error;
    })
        reader.readAsDataURL(file);
   }

然后可以在您的代码中将其合并为..flatMap(file => readFile(file))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM