项目场景:导出 Excel
往往业务中有这样的需求,导出 Excel 报表。通常技术实现由后端返回文件流,前端生成文件并下载,这也是考虑到性能问题。事实上,在多线程的加持下,纯前端也完全可以实现,以下为 Comlink 的代码写法(10 万数据):解决方案:
main.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/comlink/dist/umd/comlink.js"></script>
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>
<script src="https://unpkg.com/file-saver/dist/FileSaver.min.js"></script>
</head>
<body>
<button id="btn">Download</button>
<p id="time"></p>
<script>
const button = document.querySelector('#btn');
const worker = new Worker("worker.js");
// 使用 Comlink 包装
const getWorkBook = Comlink.wrap(worker);
// 点击触发下载
async function download() {
button.disabled = true;
// 生成 xlsx 文档的 blob 数据
const blob = await getWorkBook(100000);
// 下载
saveAs(blob, "test.xlsx");
button.disabled = false;
};
button.addEventListener('click', download);
// 观察时间是否卡顿
setInterval(() => {
document.querySelector('#time').innerHTML = new Date().toLocaleTimeString();
}, 1000);
</script>
</body>
</html>
worker.js
importScripts("https://unpkg.com/comlink/dist/umd/comlink.js");
importScripts("https://unpkg.com/xlsx/dist/xlsx.full.min.js");
// 模拟生成 Excel 并导出
const getWorkBook = (count) => {
const aoa = [];
for (let i = 0; i < count; i++) {
const arr = []
for (let j = 0; j < 10; j++) {
if (i === 0) {
arr.push(`Column${j + 1}`);
continue;
}
arr.push(Math.floor(Math.random() * 100));
}
aoa.push(arr);
}
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(aoa);
XLSX.utils.book_append_sheet(wb, ws, 'Sheet');
// XLSX.writeFile 无法获取 DOM,故采用此写法
const data = XLSX.write(wb, { type: 'array' });
return new Blob([data],{type:"application/octet-stream"});
};
Comlink.expose(getWorkBook);
可以看出,采用了 Comlink 的代码非常整洁,并且极易扩展
友情链接