如何用javascript编写简单的异步函数

如何用javascript编写简单的异步函数,javascript,asynchronous,Javascript,Asynchronous,我想调用一个javascript函数,它需要很长时间(5秒)才能完成,而不会冻结客户端的浏览器。他们单击按钮开始操作,然后在操作完成时收到通知。目前我写了一些类似的东西 $(document).ready(function(){ $('#tokenbutton').click(function(){ // IMMEDIATE EFFECT $('#tokenbutton').attr("disabled",true).val("Computing..."

我想调用一个javascript函数,它需要很长时间(5秒)才能完成,而不会冻结客户端的浏览器。他们单击按钮开始操作,然后在操作完成时收到通知。目前我写了一些类似的东西

$(document).ready(function(){
    $('#tokenbutton').click(function(){

        // IMMEDIATE EFFECT
        $('#tokenbutton').attr("disabled",true).val("Computing...");

        var callback = function(resultsFromExpensiveOperation){
            // CALLBACK EFFECTS
            $('#tokenbutton').val("Token computed");
            $('#submitbutton').attr("disabled",false);
            // ...
        };                  

        // FREEZES BROWSER
        doExpensiveOperation(callback);
    });
});

但当我运行浏览器时,它会冻结我的浏览器。如何更改它,使其不会冻结我的浏览器?

用例 创建一个将数据返回回调的非Ajax独立进程

解决方案 要求 浏览器必须:

  • 支持HTML5
  • 支持网络工作者
结构 使用逻辑为单独的线程化进程创建单独的文件。此文件必须包含以下代码:

postMessage( //data )
代码
没有真正的异步是javascript,因此没有多线程或类似的东西。不过,有一种方法可以使长时间运行的功能在某些情况下不会冻结浏览器

您可以使用setInterval或setTimeout函数一次执行长时间运行任务的一小部分,因此每一部分都需要几分之一秒的时间,然后ui再次响应几分之一秒,直到下一部分运行。这在功能上使ui保持响应性,并且不会在代码处理上增加太多时间(如果有的话)。比如说

长时间运行的代码

function doSomething(){
   for(var x = 0; x < 10000; x++){
      // do something 
   }
}
// doing it like this could take forever and lock up the browser
函数doSomething(){
对于(变量x=0;x<10000;x++){
//做点什么
}
}
//这样做可能会花费很长时间并锁定浏览器
分解代码

var total = 0;
setTimeout(doSomething, 4);

function doSomething(){

     for(total = total; total + 100 < 100; total++){
        // do something 
     }
     if(total < 10000){
        setTimeout(doSomething, 4);
     }
}
// doing it like this stops the browser from freezing but does not save any time.
var总计=0;
设置超时(剂量测量,4);
函数doSomething(){
对于(总计=总计;总计+100<100;总计++){
//做点什么
}
如果(总数<10000){
设置超时(剂量测量,4);
}
}
//这样做可以阻止浏览器冻结,但不会节省任何时间。
有几件事,, 我在setTimout中加了一个4毫秒的时间,因为这实际上是js将要除去的最低值,即使你加1,它默认为4

我使用了setTimeout模式而不是setInterval来防止下一个间隔在前一个on结束之前运行

最后,这种模式并不适用于所有情况。它最适合循环和基于序列的操作


希望有帮助

我们在谈论什么样的“昂贵手术”?在一台普通的现代计算机上,5秒的处理器时间是一个很大的处理过程。很确定你不能在浏览器中完成这项工作,因为只有一个JS线程。在过去,我已经把它分块,并且有一个计时器启动,这样我就可以继续下一块了。具有讽刺意味的是,这是一个穷人的线程。@Bart对网络工作者的支持似乎还可以,但并不令人惊讶。您可能会错过15%的浏览器。只有WebWorkers才能在浏览器中异步执行JavaScript。但正如David Ehrmann所说,异步性并不是防止浏览器冻结的必要条件。这不应该是
typeof Worker==“function”
?我想在分解的版本中需要一个额外的计数器变量。你可能是对的,我从头开始就写了它,更多的是为了展示设计模式,而不是其他任何东西,因为OP确实给出了他的doExpensiveOperation()实际做了什么的细节
function doSomething(){
   for(var x = 0; x < 10000; x++){
      // do something 
   }
}
// doing it like this could take forever and lock up the browser
var total = 0;
setTimeout(doSomething, 4);

function doSomething(){

     for(total = total; total + 100 < 100; total++){
        // do something 
     }
     if(total < 10000){
        setTimeout(doSomething, 4);
     }
}
// doing it like this stops the browser from freezing but does not save any time.