一道关于大数据加载问题,应该如何解决呢,是不是可以考虑使用web worker做点事情?

584 阅读2分钟

最近一个团队,是做3d数据渲染的。在渲染之前需要做很多数据的加载来绘制webGL的建模数据。

身为技术顾问的我,因为做了多年的互联网开发。给出的方案是大多数的人。都会想到的,首先,先拿到后端的数据总数,然后算出分页数。然后利用Promise.all和for进行数据的单位时间内的加载。但如果使用rxjs的话这有点像fiber的算法,把大的东西换成小的东西操作,让用户感觉到没有卡顿的感觉。rxjs还提供恢复,暂停这些操作...

这方案是在html5之前,大家都会往这个点去做的。那如果在html5之后,我们有没有什么刚好的解决方案呢?这个时候我就想到了web worker

web worker

Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是UI)线程运行而不被阻塞。

由于js线程和ui线程是分开的,那么我们能不能用来做一点事情呢?ui线程开一个监听的事件,然后js线程去做预取数据(注意的是自线程与主线程的DOM与BOM是不共享的)

预取数据

有时候为了提升数据加载速度,可以提前使用Worker线程获取数据,因为Worker线程是可以是用 XMLHttpRequest 的。

预渲染

在某些渲染场景下,比如渲染复杂的canvas的时候需要计算的效果比如反射、折射、光影、材料等,这些计算的逻辑可以使用Worker线程来执行,也可以使用多个Worker线程,这里有个射线追踪的示例。

复杂数据处理场景

某些检索、排序、过滤、分析会非常耗费时间,这时可以使用Web Worker来进行,不占用主线程。

比如图片的预加载

// 主线程

let w = new Worker("js/workers.js");

w.onmessage = function (event) {

    var img = document.createElement("img");

    img.src = window.URL.createObjectURL(event.data);

    document.querySelector('#result').appendChild(img)

}
// worker线程

let arr = [...好多图片路径];

for (let i = 0, len = arr.length; i < len; i++) {

    let req = new XMLHttpRequest();

    req.open('GET', arr[i], true);

    req.responseType = "blob";

    req.setRequestHeader("client_type", "DESKTOP_WEB");

    req.onreadystatechange = () => {
        if (req.readyState == 4) {
        postMessage(req.response);
        }
    }

    req.send(null);

}
  1. 虽然使用worker线程不会占用主线程,但是启动worker会比较耗费资源
  2. 主线程中使用XMLHttpRequest在请求过程中浏览器另开了一个异步http请求线程,但是交互过程中还是要消耗主线程资源