【问题标题】:Why do I need to have anonymous function in the setTimeout for this code to work?为什么我需要在 setTimeout 中有匿名函数才能使此代码正常工作?
【发布时间】:2026-02-18 10:00:01
【问题描述】:

我正在看一个Nodejs的教程,但是我看不懂这个sn-p的代码,请给我解释一下。

function async(arg, callback) {
  console.log('do something with \''+arg+'\', return 1 sec later');
  setTimeout(function() { callback(arg * 2); }, 1000);
}
function final() { console.log('Done', results); }

var items = [ 1, 2, 3, 4, 5, 6 ];
var results = [];
var running = 0;
var limit = 2;

function launcher() {
  while(running < limit && items.length > 0) {
    var item = items.shift();
    async(item, function(result) {
      results.push(result);
      running--;
      if(items.length > 0) {
        launcher();
      } else if(running == 0) {
        final();
      }
    });
    running++;
  }
}

launcher();

此代码产生 run 2x 然后暂停一秒钟然后再次运行 2x 直到 items 数组中没有项目。

但是当我在 setTimeout 中移除匿名函数时:

setTimeout(callback(arg*2), 1000);

然后代码运行没有停止任何一秒钟。为什么?

【问题讨论】:

  • 为什么不等一秒钟就停止运行?因为 setTimeout 会导致 1 秒的“等待”并且您将其删除。
  • 我去掉了匿名函数,但是settimeout仍然在1秒内调用了callback(arg*2)。

标签: javascript node.js


【解决方案1】:

然后代码运行时不会停止。为什么?

因为不是将函数传递给setTimeout,而是将函数调用的返回值传递给它。

函数调用立即执行,然后setTimeout 不处理返回值,因为它(可能)不是字符串或函数。

不要删除匿名函数包装器。

【讨论】:

    【解决方案2】:

    之所以需要匿名委托,是因为 setTimeout 需要一个 function 类型的对象作为它的第一个参数。

    所以你可以直接给它一个预定义的函数名:

    function foo()
    {
    //do something
    }
    
    setTimeout(foo, 1000);
    

    或委托:

    setTimeout(function(){/*dosomething*/}, 1000);
    

    但是这个:

    setTimeout(foo(param), 1000);
    

    无效,因为 foo(param) 在此上下文中的语义不正确。

    另一种方法是执行以下操作:

    setTimeout("foo(param);", 1000);
    

    因为 setTimeout 也会接受一个函数字符串,但这是个坏主意,因为你失去了当前作用域并且调试起来很痛苦。

    【讨论】:

    • 永远不要将字符串传递给setTimeout。它会被评估,速度很慢,难以调试并且会破坏范围。
    • 问题是问为什么需要它。该代码出现在原始问题中。
    • foo(param) 在语法上是正确的,并且给定function foo(bar) { return function () { alert(bar); }; } 它将起作用。
    • 是的,它语法正确(它是合法的 JS),它只是不语义正确(它计算出一个无意义的结果)。