![](/img/trans.png)
[英]How to handle async update onUpdate of each field and keep ids using redux-form and 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.