Javascript的时间延迟

时间:2012-07-09 15:43:29

标签: javascript

函数PS.Tick()每100毫秒调用一次,其工作是调用NPC的AI函数,以便它们可以移动:

PS.Tick = function ()
{
"use strict";
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
    NPCAI(NPCid);
};
}; 

但是我希望NPC不会每100毫秒同时移动一次,但是按照自己的频率进行移动,所以我尝试了这段代码:

PS.Tick = function ()
{
"use strict";
for (NPCid = 0; NPCid < NPCnumber; NPCid++)
{
    var timeout = 0;
    timeout = PS.Random (1000);
    setTimeout("NPCAI(NPCid)",timeout);
};
};

现在,他们根本不动。为什么?如何让它们以不同的时间间隔移动?

3 个答案:

答案 0 :(得分:2)

制作

for (NPCid = 0; NPCid < NPCnumber; NPCid++) {
    var timeout = 0;
    timeout = PS.Random (1000);
    (function (id) {
        setTimeout(function(){NPCAI(id)},timeout);
    })(NPCid); };

需要额外的功能来捕获闭包中的ID。没有它,只会在每个实例中传递循环的最后一个ID。

答案 1 :(得分:0)

  

现在,他们根本不动。为什么呢?

有几个可能的原因:

  • 如果NPCid未在任何地方声明:您的代码正在抛出ReferenceError

  • 如果NPCid在某处声明但它不是全局的:当您将字符串传递给setTimeout时,它不会在当前执行上下文中得到评估,也无法访问到NPCid。通常,不要将字符串传递给setTimeout

  • 如果NPCid是全局的:当执行延迟代码时,它们都会看到NPCid的相同值,这是结束时的值

相反:如果你在NodeJS上做这个(我只是从你正在做的事情推断这个),你可以这样做):

PS.Tick = function ()
{
    "use strict";

    // (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)

    for (NPCid = 0; NPCid < NPCnumber; NPCid++)
    {
        var timeout = 0;
        timeout = PS.Random (1000);
        setTimeout(NPCAI, timeout, NPCid); // NodeJS (and Firefox) ONLY!!
    }
};

这是有效的,因为在NodeJS(和Firefox)上,setTimeout可以接受传递给要调用的函数的参数。

如果您没有使用NodeJS或Firefox,但您可以访问ES5的Function#bind,则可以执行以下操作:

PS.Tick = function ()
{
    "use strict";

    // (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)

    for (NPCid = 0; NPCid < NPCnumber; NPCid++)
    {
        var timeout = 0;
        timeout = PS.Random (1000);
        setTimeout(NPCAI.bind(undefined, NPCid), timeout);
    }
};

Function#bind返回一个函数,该函数在调用时将使用特定的this值和您提供的参数调用原始函数。

如果没有,您可以编写自己的bind,或者这样做:

PS.Tick = function ()
{
    "use strict";

    // (I'm assuming NPCid is defined somewhere; if not, add `var NPCid;` here)

    for (NPCid = 0; NPCid < NPCnumber; NPCid++)
    {
        var timeout = 0;
        timeout = PS.Random (1000);
        setTimeout(makeHandler(NPCid), timeout);
    }

    function makeHandler(id) {
        return function() {
            NPCAI(id);
        };
    }
};

这可以通过创建一个函数来实现,该函数在被调用时转身并使用我们传入其中的值调用NPCAI。

答案 2 :(得分:-1)

你的setTimeout不会调用任何函数,

试试这个:

setTimeout(function(){ NPCAI(NPCid); }, timeout);

或者更好地使用每个NPC的设置间隔,但是使用大量的超时和间隔是非常低效的,所以要注意并准备好延迟。