javascript中的异步行为

时间:2014-05-15 10:54:50

标签: javascript

考虑以下javascript算法:

for(var i = 0; i < 50; i ++){
    console.log('starting :', i);
    getPrimes(1000000);
    (function(i){
        setTimeout(function(){
            console.log('done :', i);
        }, 1000);
    })(i);
}

function getPrimes(max) {
    var sieve = [], i, j, primes = [];
    for (i = 2; i <= max; ++i) {
        if (!sieve[i]) {
            // i has not been marked -- it is prime
            primes.push(i);
            for (j = i << 1; j <= max; j += i) {
                sieve[j] = true;
            }
        }
    }
    return primes;
}

for循环启动getPrimes函数需要一些时间,然后运行另一个超时为1秒的函数。考虑到这个算法,我期望在控制台上得到的是&#34;开始&#34;和&#34;完成&#34;从开始到结束排序的行,但不一定从1到50排序。

实际上我得到的是50行&#34;开始&#34; (这需要一些时间来处理)然后不断完成50行&#34;完成&#34;。

我的问题是为什么?逻辑告诉我在运行for循环时至少应该完成一个timout回调,因为javascript是单线程异步,它应该显示一行&#34; done&#34;介于&#34;开始&#34;

的某些行之间

可能是因为素数计算需要所有的CPU功率吗?

由于

3 个答案:

答案 0 :(得分:3)

问题出在javascrypt events数组中,所以所有超时函数运行都进入数组,javascript虚拟机在for循环完成运行后运行它们。为了更好地理解,ypu可以运行以下代码:

for( var i=0; i<10; i++) {
  console.log(i);
  setTimeout(function(){
       console.log('hhh');
  },0)
}

因此输出将是setTimeout之前的所有console.logs,然后是所有setTimeout的console.log。

当我们调用setTimeout时,超时事件会排队。然后继续执行: 运行setTimeout调用后的行,然后是之后的行,依此类推, 直到没有线路为止。只有这样才能生成JavaScript虚拟机 问,“队列里有什么?” 如果队列中至少有一个事件有资格“开火”(如500ms 在1000ms前设置的超时),VM将选择一个并调用其处理程序 (例如,我们传递给setTimeout的函数)。当处理程序返回时,我们 回到队列。 输入事件的工作方式相同:当用户使用a单击DOM元素时 单击处理程序附加,单击事件排队。但处理程序不会 执行直到所有当前正在运行的代码完成(并且可能直到 在其他事件发生之后)。这就是使用Java-的网页的原因 脚本不明智地往往没有反应。

在你的具体问题中,他们一起被解雇只是因为你把它们全部放在“事件数组”中,所以他们所有人的时间都相同,你等待的时间就是你在setTimeout中设置的时间+计算时间的较小增量。

在Angular中进行编程时,我使用它来确保我的代码在完成任何其他操作之后运行,因此我只是将setTimeout()放在没有时间值的情况下,并且内部代码在其他所有内容之后执行。

答案 1 :(得分:0)

Javascript不是多线程的:代码将继续执行,直到它返回主循环。

答案 2 :(得分:0)

循环发生50次,显示开始

然后在每个循环中,代码(function(){})();在读取后立即执行,因为它是自我调用

setTimeout将在for循环

之后执行
for-loop timer: timer started
"starting :" 0
selfinvokingfunction timer: timer started 
selfinvokingfunction timer: 0ms
"starting :" 1 
selfinvokingfunction timer: timer started
selfinvokingfunction timer: 0ms 
"starting :" 2 
selfinvokingfunction timer: timer started 
selfinvokingfunction timer: 0ms 
for-loop timer: 656ms 
setTimeout timer: timer started 
"done :" 0 
setTimeout timer: 0ms 
setTimeout timer: timer started 
"done :" 1 
setTimeout timer: 0ms 
setTimeout timer: timer started 
"done :" 2 
setTimeout timer: 0ms

使用console.timeconsole.timeEnd来检查执行顺序相同的时间,for循环是否以秒结束。