我试图一次只处理一个给定的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