在没有阻止的情况下执行密集型javascript的最佳方法是什么?

时间:2014-11-14 23:02:10

标签: javascript multithreading three.js webgl

所以,我正在使用webgl加载一个3d模型,并有一些代码在显示之前对它执行一些操作。

问题在于这需要几秒钟的时间并完全阻止用户在此期间做任何事情。在此期间你甚至无法滚动,这已经够糟糕了。我听说在javascript中没有多线程这样的东西,但我还是需要它来阻止主线程。

我甚至尝试了一个设置,我将其加载到iframe并使用 window.postMessage 消息事件监听器,但它似乎是框架的域对于它的javascript也使用相同的线程,所以它不起作用。其他人都有处理CPU密集型代码的解决方案,这样用户就不会做任何事情吗?

2 个答案:

答案 0 :(得分:4)

至少目前还没有一个简单的答案

  1. WebWorkers

    Web worker在另一个线程中运行JavaScript。不幸的是,他们被允许做的事情非常有限。通常,您所能做的就是来回传递消息。 WebWorker无法触及DOM,无法进行WebGL或制作Canvas(尚未)。您当前所能做的就是联网并将字符串和/或类型化数组传入WebWorker或从WebWorker传递。

    如果您正在做的事情需要花费大量时间,可以将其传递回JSON字符串和/或类型化数组中的主线程,这可能对您有用。

  2. 状态机

    在JavaScript中处理此问题的常用方法是让您的加载程序在多个状态下执行操作,以便您可以将其称为类似

    function doALittleMoreWork() {
       ...
       if (theresStillMoreWorkToDo) {
         setTimeout(doALittleMoreWork, 16);
       } 
    }
    

    或者那些东西。 doALittleMoreWork完成了部分工作,然后记住了足够的状态,所以当再次调用时,它可以在停止的地方继续。这就是O3D loader worked

  3. 的方式
  4. 您可以尝试使用ES6 generators

    生成器有效地让您轻松创建状态机。浏览器还不支持ES6,但有些库可让您现在使用此功能,例如Google Traceur

    事实上,如果你写一个像

    这样的简单生成器
    function *foo() {
        console.log("do first thing");
        yield 1;
        console.log("do 2nd thing");
        yield 2;
        console.log("do 3rd thing");
        yield 3;
        console.log("do 4th thing");
        yield 4;
        console.log("do 5th thing");
        yield 5;
    }
    

    然后通过跟踪#{3}}跟上面的#2

  5. 运行它

答案 1 :(得分:1)

Web workers API绝对是你需要的