nodeJS - 无法理解代码的行为

时间:2015-11-29 14:03:01

标签: event-loop single-threaded

function placeOrder(orderNo) {
console.log("Order is: " + orderNo);

setTimeout(deliver(orderNo),5000);
}

function deliver(orderNo) {
    console.log("Item is delivered with Order No.- " + orderNo);
}

placeOrder(1);
placeOrder(2);
placeOrder(3);
placeOrder(4);
placeOrder(5);
placeOrder(6);

上面的代码是nodejs代码,其输出应为:

order No:1
order No:2
order No:3
order No:4
order No:5
order No:6
Item is delivered with order No.- 1
Item is delivered with order No.- 2
Item is delivered with order No.- 3
Item is delivered with order No.- 4
Item is delivered with order No.- 5
Item is delivered with order No.- 6

但我得到的输出是这样的:

order No:1
Item is delivered with order No.- 1
order No:2
Item is delivered with order No.- 2
order No:3
Item is delivered with order No.- 3
order No:4
Item is delivered with order No.- 4
order No:5
Item is delivered with order No.- 5
order No:6
Item is delivered with order No.- 6

我在单线程和异步回调的概念中出错了。请有人解释一下代码是如何工作的。

3 个答案:

答案 0 :(得分:1)

替换:

setTimeout(deliver(orderNo),5000);
}

使用:

setTimeout(function() {
    deliver(orderNo); 
}, 5000);

setTimeout函数的第一个参数是函数指针。在您的代码中,您传递了deliver(orderNo)调用的结果,这只是一些void参数。现在,您可以摆脱console.log函数中的placeOrder

答案 1 :(得分:1)

您使用了错误的setTimeout签名定义

var timeoutID = window.setTimeout(func, [delay, param1, param2, ...]);
var timeoutID = window.setTimeout(code, [delay]);

因此,您的代码应为:

setTimeout(function() {
  deliver(orderNo);
}, 5000);

答案 2 :(得分:0)

TL;博士

这是一个语法问题。您将错误的参数 type 传递给setTimeout

改变这个:

setTimeout(deliver(orderNo),5000);

到此:

setTimeout(deliver, 5000, orderNo);

请注意,此语法在IE 9或更低版本中不起作用。

解释

如果您查看setTimeout on MDN的文档,您会看到第一个参数是FunctionString,包含JavaScript代码。在您的情况下,您尝试传入一个接受此语法的函数:

setTimeout(func, [delay, param1, param2, ...]);

param1, param2, ...是函数的参数func。你正在做的是传递函数返回的而不是函数本身

由于您传递了值,setTimeout未按预期执行。你仍然从deliver获得输出的原因是因为它实际上是在运行时而不是setTimeout执行的。这与调用deliver本身几乎相同。

作为参数的函数

请记住JavaScript中的函数是First-Class Citizens,这意味着它们可以作为参数传递给函数。

加成

您可以使用一些替代语法。

字符串

评论中提及的pokeybit

setTimeout("deliver("+orderNo+");",5000);

允许您立即使用该功能及其参数。但是,由于字符串连接,这是一种更丑陋的语法。

匿名函数

将setTimeout与匿名函数一起使用:

setTimeout(function() {
  console.log("Item is delivered with Order No.- " + orderNo);
}, 5000);

这可以说是最常见,最安全的语法。

返回匿名函数的函数

你可以保持:

setTimeout(deliver(orderNo),5000);

如果您将deliver定义为返回Function的函数:

function deliver(orderNo) {
  return function() {
    console.log("Item is delivered with Order No.- " + orderNo);
  }
}

由于此值返回一个函数,因此它是setTimeout的正确类型。