我試圖一次只處理一個給定的ID的下載。我希望它是非阻塞的,所以「不同的文件ID」可以並行下載,這就是爲什麼我在做takeEvery
。我想放棄,如果「相同的文件ID」已在進行中。takeEvery,但它是丟棄每一個
一旦行動DOWNLOAD_FILE
被派遣,我設置在減速器,file.isDownloading = true
。然而downloadFileWorker
總是發現它是真實的並且丟棄。
這裏是我的傳奇:
const DOWNLOAD_FILE = 'DOWNLOAD_FILE';
export function downloadFile(id) {
return {
type: DOWNLOAD_FILE,
id
}
}
function* downloadFileWorker(action) {
const { id } = action;
const state = yield select();
const files = state;
const file = files.find(file => file.id === id);
if (file.isDownloading) {
console.log('discontinuing worker as file is already downloading');
return;
} else {
console.log('OK CONTINUE TO DOWNLOAD');
const res = yield call(fetch, ...);
const json = yield call(res.json);
console.log('json:', json);
}
}
function* downloadFileWatcher() { // i think i can call this downloadFileSaga
yield takeEvery(DOWNLOAD_FILE, downloadFileWorker);
}
我們在這裏看到這第一個發現在該州的文件,如果它isDownloading
那麼它不會繼續(在downloadFileWorker
)。
當DOWNLOAD_FILE
動作被觸發時,在reducer中我將文件設置爲isDownloading
,所以我的工作人員總是放棄。這是我的減速器:
export default function reducer(state=INITIAL, action) {
switch(action.type) {
case DOWNLOAD_FILE: {
const { id } = action;
const files = state;
if (!files) return state;
const file = files.find(file => file.id === id);
if (!file) return state;
if (file.isDownloading) {
console.log('discarding reducer action, as file is already downloading');
return state;
}
return files.map(file => file.id !== id ? file : { ...file, isDownloading:true })
}
default: return state;
}
}
非常感謝Martin對你的幫助。我希望避免通過'DOWNLOAD_FILE_STARTED'創建另一個動作,因爲我想使用'DOWNLOAD_FILE' - 因爲現在該動作被reducer忽略,我想很好地使用它,這是不可能的? – Noitidart
我想到另一種方式來做到這一點,我更新了我的答案,包括其他解決方案:) –
非常酷,謝謝你馬丁!所以'watcher'總是在'worker'之前觸發的'reducer'之前觸發?這是生命週期嗎? – Noitidart