簡體   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