前端异步加载多个分包数据的处理

    技术2024-12-29  22

    前端异步加载多个分包数据的处理以及单线程与多线程对比

    使用场景最佳实现方式单线程加载与多线程加载的对比

    使用场景

    前端需要加载一些分包的数据,最终拼成一个完整数据包时,需要考虑回包的顺序以及最后一个回包收到的事件通知。最容易想到的方式是先分配好每个数据包的位置,每次收到数据包时,检查数据包缓存是否排满,如果排满就使用发布订阅模式通知事件。

    最佳实现方式

    直接切入正题,走过了几条弯路以后才发现Promise.all方法才是最合适的解决方式。

    //单线程 async function mainLoad() { let arr = modelObj.bagInfo.body.map((v) => { //这里可以是任何promise封装过的异步函数 return ajaxGet( v ,"arraybuffer") }) modelObj.vertex = await Promise.all(arr) }

    没错,就是这么简单,Promise.all会根据arr参数里promise对象的顺序去返回相同顺序的数据包。有类似需求的同学们,请认准Promise.all。

    单线程加载与多线程加载的对比

    如果使用多线程分包加载数据会不会快呢? h5标准的worker线程也出来很多年了,如果只是纯前端开发,基本用不到。写个东西试试,用数据说话。

    //多线程 async function workerLoad() { let arr = modelObj.bagInfo.body.map((v,i) => { return spawnWorker(i) }) modelObj.vertex = await Promise.all(arr) } // 生成多线程 function spawnWorker(i) { return new Promise((resolve, reject) => { let worker = new Worker('./worker.js', { name: i }) worker.postMessage(modelObj.bagInfo.body[i]) worker.onmessage = function (event) { resolve(event.data.res) } }) }

    worker.js里的代码就是个ajax请求分包数据,收到后通知主线程,注意worker线程有一些内置对象是获取不到的,所以它能干的事情有限。 分5个数据包加载,分大包和小包,下面是各类情况下的结果。

    多线程加载大包或小包都要更慢??? 看看下面的waterfall图就知道了,多线程还要多调用5个worker去生成ajax请求,线程之间还要有开销,所以肯定就慢了。 观察每一个请求发送的时间,单线程因为异步的关系,与多线程一样,几乎都是同时发送的。 查询有关浏览器事件循环模型相关资料,ajax请求本来就是启用其他线程去完成的,所以用worker纯属多此一举。 难道worker线程在前端就是鸡肋么? 当然不是,在webGL领域以及前端人工智能领域,把一些大计算量的工作放在worker去处理才能充分利用多核cpu,做做页面的话好像确实用不到。

    Processed: 0.009, SQL: 9