我使用react,electron,nodejs,asyncjs redux和thunk。 我写了下面的代码,它应该下载一个文件列表并将其写入磁盘。在我的代码中,当用户按下按钮时,我调用此actionCreator:
export function downloadList(pack) {
return (dispatch, getState) => {
const { downloadManager } = getState();
async.each(downloadManager.downloadQueue[pack].libs, async (url, callback) => {
const filename = url.split('/').pop().split('#')[0].split('?')[0];
await downloadFile(url, `dl/${filename}`);
callback();
}, (err) => {
if (err) {
console.log('A file failed to process');
} else {
dispatch({
type: DOWNLOAD_COMPLETED,
packName: pack
});
}
});
};
}
async function downloadFile(url, path) {
const file = fs.createWriteStream(path);
const request = https.get(url, (response) => {
response.pipe(file);
file.on('finish', () => {
file.close();
});
}).on('error', (err) => { // Handle errors
fs.unlink(path); // Delete the file async. (But we don't check the result)
});
}
它做了它应该做的事情,但是当它这样做时,它会阻止整个用户界面。我真的无法理解为什么它会发生,因为如果我使用
setTimeout
在async.each内部延迟3000ms,它不会阻止UI。 另一个奇怪的行为是,如果我使用asyncJS的eachLimit函数,它只是下载我的文件的限制,所以如果我想下载100个文件,但我将eachLimit设置为10并行,它只是下载前10个文件,然后停止。你能告诉我这件事吗? 我想使用axios来下载文件,因为它不需要知道网址是http还是https,但是我无法找到使用带有响应类型的axios的任何资源
答案 0 :(得分:0)
我可以回答第一部分。几乎每个现有的JavaScript实现都在一个线程上运行。这意味着运行时是并发的,但不是并行的,即运行时一次只做一件事。这意味着如果有一个函数调用需要一段时间,它将阻止其他一切。因此,downloadList
函数中的某些内容阻止了事件循环。但是,如果使用setTimeout
,则downloadList
函数将被推送到消息队列,这将取消阻止事件并允许呈现UI。有关事件循环的更多信息,请查看this video