在下面的javascript程序中(欧拉问题5)我正在练习编写异步/非阻塞功能。该程序试图找到可被数字1-10整除的最小数字。 2520是第一个最小的,这是程序应该停止的地方。
我设置了程序,这样如果函数一起运行,那么第二个checkNum应该先完成并先打印第二个,然后是第一个,但是没有发生?
如何让功能同时运行,而不是一个接一个地运行?我期待来自我调用的第二个checkNum函数的回调首先被调用(因为它开始接近答案),然后是第一个,但这不是发生的事情。非常感谢!
var divides = function(a, b) {
return b % a == 0;
};
function checkNum(counter, callback) {
var noRemainder = 0;
var forward = true;
while (forward)
{
for (var i = 1; i <= 10; i++) {
if (divides(i, counter))
{ noRemainder++; }
}
if (noRemainder == 10) {
console.log(counter);
forward = false;
callback(counter);
} else {
console.log(noRemainder);
noRemainder = 0;
counter++;
console.log(counter);
}
}
}
checkNum(1, function(counter) {
setTimeout(function(){
console.log("The counter is: " + counter)},3000)
}
);
checkNum(2500, function(counter) {
setTimeout(function(){
console.log("The counter2 is: " + counter) },3000)
}
);
答案 0 :(得分:2)
因为checkNum
是一个纯粹的CPU绑定函数 - 也就是说,它唯一能做的就是在紧密的循环中执行计算 - 没有理由让它成为异步的。该功能按定义同步;在计算完成之前,控件不会返回调用者。请考虑以下异步样式:
checkNum(n, function(err, result) {
console.log(result);
});
console.log('Next line');
...和同步风格:
console.log( checkNum(n) );
console.log('Next line');
在这两种情况下,checkNum
的结果将在 checkNum
调用其回调并且回调完成之后才会返回控件。 (将此与真正的异步函数进行比较,其中在回调获得结果之前将打印“下一行”。)
节点的真正的魔力来自于一个事实,大多数的贵的操作(如I / O)是由本地代码在一个单独的线程执行,他们正在做的时候,就调用一个JavaScript主线程上的回调。因此,执行JavaScript所花费的时间非常少,因此您的应用程序执行得非常好。
但是,如果您发现自己在JavaScript中编写了昂贵的循环和类似的计算,则必须记住,您将在函数运行的时间内阻止所有内容。在其他线程上发生的事情将排队,在昂贵的函数返回之前,您的应用程序代码将无法执行任何操作。
根据性能顺序,有几种方法可以解决此限制:
nextTick
开始处理每个块。这允许任何排队的事件在块之间进行处理。fork
来执行此操作,因为它带有内置IPC。 Here's an example fibonacci calculator.请记住,这会带来开销:启动新节点进程需要大约30毫秒和至少10 MB的RAM。答案 1 :(得分:0)
您不能让这些函数真正同时运行,就好像您有多个并行运行的线程一样。这是因为Javascript是单线程,而不是多线程。你真正得到的最好的是“sorta kinda”并行操作,实际上,它并不是平行的。
答案 2 :(得分:0)