如何制作非阻塞的javascript代码?

use*_*828 27 javascript asynchronous callback nonblocking

如何进行简单的非块Javascript函数调用?例如:

  //begin the program
  console.log('begin');
  nonBlockingIncrement(10000000);
  console.log('do more stuff'); 

  //define the slow function; this would normally be a server call
  function nonBlockingIncrement(n){
    var i=0;
    while(i<n){
      i++;
    }
    console.log('0 incremented to '+i);
  }
Run Code Online (Sandbox Code Playgroud)

输出

"beginPage" 
"0 incremented to 10000000"
"do more stuff"
Run Code Online (Sandbox Code Playgroud)

如何形成这个简单的循环以异步执行并通过回调函数输出结果?这个想法是不阻止"做更多的东西":

"beginPage" 
"do more stuff"
"0 incremented to 10000000"
Run Code Online (Sandbox Code Playgroud)

我已经尝试过关于回调和延续的教程,但它们似乎都依赖于外部库或函数.他们都没有在真空中回答这个问题:如何编写Javascript代码是非阻塞的??


在询问之前,我非常努力地寻找这个答案; 请不要以为我没看.我发现的一切都是Node.js特定的([1],[2],[3],[4],[5])或其他特定于其他函数或库([6],[7],[8],[9],[10],[11]),特别是JQuery和setTimeout().请帮我用Javascript编写非阻塞代码,而不是Javascript和Node等Javascript编写的工具. 请在将其标记为重复之前重新阅读该问题.

Aln*_*tak 21

要使循环无阻塞,必须将其分成几个部分,并允许JS事件处理循环在继续执行下一部分之前使用用户事件.

实现这一目标的最简单方法是做一定量的工作,然后setTimeout(..., 0)用来排队下一部分工作.至关重要的是,排队允许JS事件循环处理在此期间排队的任何事件,然后再进行下一项工作:

function yieldingLoop(count, chunksize, callback, finished) {
    var i = 0;
    (function chunk() {
        var end = Math.min(i + chunksize, count);
        for ( ; i < end; ++i) {
            callback.call(null, i);
        }
        if (i < count) {
            setTimeout(chunk, 0);
        } else {
            finished.call(null);
        }
    })();
}
Run Code Online (Sandbox Code Playgroud)

用法:

yieldingLoop(1000000, 1000, function(i) {
    // use i here
}, function() {
    // loop done here
});
Run Code Online (Sandbox Code Playgroud)

请参阅http://jsfiddle.net/alnitak/x3bwjjo6/以获取演示,其中callback函数仅将变量设置为当前迭代计数,并且基于单独setTimeout的循环轮询该变量的当前值并使用其值更新页面.


And*_*man 8

带回调的SetTimeout是要走的路.但是,要了解您的功能范围与C#或其他多线程环境中的功能范围不同.

Javascript不会等待你的函数的回调完成.

如果你说:

function doThisThing(theseArgs) {
    setTimeout(function (theseArgs) { doThatOtherThing(theseArgs); }, 1000);
    alert('hello world');
}
Run Code Online (Sandbox Code Playgroud)

在您通过的功能之前,您的警报将会触发.

不同之处在于警报阻止了线程,但是您的回调没有.

  • 与 @Alnitak 的答案相比,我更喜欢这个答案的清晰度。但是,正如 @Alnitak 指出的那样,值得注意的是,人们还可以使用 setTimeout(..., 0) 来避免不必要的等待时间。它仍然是非阻塞的! (3认同)

归档时间:

查看次数:

29483 次

最近记录:

7 年,1 月 前