需要延迟javascript执行,但setTimeout证明存在问题

问题描述:

感谢您花时间帮助我。需要延迟javascript执行,但setTimeout证明存在问题

我正在写一个游戏,其中一个动画火车图标沿着给定的路径移动到一个目的地,在途中停靠点。这是为了给人留下动画的印象。

游戏编码在Facebook的Javascript。我需要找到一种方法让火车图标暂停1秒钟,然后继续前进到下一个航点。我希望找到一个让我暂停脚本执行一秒钟的功能,但是JS中似乎没有这样的功能。于是,我就setTimeout的,但我的这个主要问题是双重的:

  1. 我需要一个数组传递到回调函数作为参数,我无法弄清楚如何使setTimeout的做到这一点。

  2. 我终于成功地使用setTimeout来执行5个航路点的列车动画代码(我通过使用全局变量克服了1中的问题)。不幸的是,似乎所有五次setTimeout调用几乎同时排队,导致第一次setTimeout等待一秒钟,然后它们全部开火,破坏了火车动画的错觉。

我一直在争取连续六个小时的这个问题。如果有人能帮我找到解决方案,那将是美好的。谢谢!

下面的代码:

function myEventMoveTrainManual(evt, performErrorCheck) { 
     if(mutexMoveTrainManual == 'CONTINUE') { 
     var ajax = new Ajax(); 
     var param = {}; 
     if(evt) { 
      var cityId = evt.target.getParentNode().getId(); 
      var param = { "city_id": cityId }; 
     } 
     ajax.responseType = Ajax.JSON; 
     ajax.ondone = function(data) { 
      var actionPrompt = document.getElementById('action-prompt'); 
      actionPrompt.setInnerXHTML('<span><div id="action-text">'+ 
       'Train en route to final destination...</div></span>'); 
      for(var i = 0; i < data.length; i++) { 
       statusFinalDest = data[i]['status_final_dest']; 
       //pause(1000); 
       gData = data[i]; 
       setTimeout(function(){drawTrackTimeout()},1000); 
       if(data[i]['code'] == 'UNLOAD_CARGO' && statusFinalDest == 'ARRIVED') { 
       unloadCargo(); 
       } else if (data[i]['code'] == 'MOVE_TRAIN_AUTO' || data[i]['code'] == 'TURN_END') { 
       //moveTrainAuto(); 
       } else { 
       // handle error 
       } 
       mutexMoveTrainManual = 'CONTINUE'; 
      } 
     } 
     ajax.post(baseURL + '/turn/move-train-final-dest', param); 
     } 

} 


function drawTrackTimeout() { 
    var trains = []; 
    trains[0] = gData['train']; 
    removeTrain(trains); 
    drawTrack(gData['y1'], gData['x1'], gData['y2'], gData['x2'], '#FF0', trains); 
    gData = null; 
} 
+0

只是一个假设堂妹没有示例代码,你里面调用任何功能数组,如果是这样,请在数组内使用设定的超时时间 – Max 2011-05-31 06:49:50

+0

一些代码示例会很棒。 – netbrain 2011-05-31 06:49:59

要传递参数,这可能会帮助您:

setTimeout(function() { 
    (function(arg1, arg2) { 
     // you can use arg1/arg2 here 
    })('something', 123); 
}, 1000); 

或者,如果您使用的是定义的函数:

setTimeout(function() { 
    someFunction('something', 123); 
}, 1000); 

它基本上开始超时;一秒钟后,该函数将被调用指定的参数。

通常,这将通过创建一个对象来完成(比如叫myTrain),有自己的所有数据和方法,然后调用一个myTrain.run mehod看起来,看看那里的火车。如果它位于两个站之间,它会以setTimeout自动呼叫,并说50ms延迟。当它到达一个电台时,它会自动调用1000ms,在电台上产生1秒的暂停。

如果您一次排队setTimeouts,那么您将冒着被其他进程延迟的风险,然后全部一起运行。

嘿,有点有趣(仔细包装)。需要一点良好的'奥原型继承的做法:

<!-- All the style stuff should be in a rule --> 
<div style="position: relative; border: 1px solid blue;"> 
    <div id="redTrain" 
    style="width:10px;height:10px;background-color:red; position:absolute;top:0px;left:0px;"></div> 
</div> 

<script type="text/javascript"> 

// Train constructor 
function Train(id) { 
    this.element = document.getElementById(id); 
    this.timerId; 
} 

// Methods 
// Trivial getPos function 
Train.prototype.getPos = function() { 
    return this.element.style.left; 
} 

// Trivial setPos function 
Train.prototype.setPos = function(px) { 
    this.element.style.left = parseInt(px,10) + 'px'; 
} 

// Move it px pixels to the right 
Train.prototype.move = function(px) { 
    this.setPos(px + parseInt(this.getPos(),10)); 
} 

// Recursive function using setTimeout for animation 
// Probably should accept a parameter for lag, long lag 
// should be a multiple of lag 
Train.prototype.run = function() { 

    // If already running, stop it 
    // so can interrupt a pause with a start 
    this.stop(); 

    // Move the train 
    this.move(5); 

    // Keep a reference to the train for setTimeout 
    var train = this; 

    // Default between each move is 50ms 
    var lag = 50; 

    // Pause for 1 second each 100px 
    if (!(parseInt(this.getPos(),10) % 100)) { 
    lag = 1000; 
    } 

    train.timerId = window.setTimeout(function(){train.run();}, lag); 

} 

// Start should do a lot more initialising 
Train.prototype.start = function() { 
    this.run(); 
} 

// Stops the train until started again 
Train.prototype.stop = function() { 
    if (this.timerId) { 
    clearTimeout(this.timerId); 
    } 
} 

// Set back to zero 
Train.prototype.reset = function() { 
    this.stop(); 
    this.setPos(0); 
} 

// Initialise train here 
var myTrain = new Train('redTrain'); 

</script> 
<p>&nbsp;</p> 
<button onclick="myTrain.start();">Start the train</button> 
<button onclick="myTrain.stop();">Stop the train</button> 
<button onclick="myTrain.reset();">Reset the train</button> 
+0

Hi Rob。你的原型对象看起来像是可以工作的。不幸的是,Facebook JS不支持原型。 – 2011-05-31 12:59:34

如何使用面向对象的原则来简化问题?创建一个“对象”列车,其具有以下方法:

//train obj 
function Train(){ 
    this.isOnWaypoint = function(){ 
    return calculateIsWayPoint() 
    } 

} 

//main logic 
var train = new Train() 
var doneWaiting = false 
var doneWaitingTimeout = undefined 
var gameLoop = setInterval(1000,function(){ 
    ... 
    if(train.isOnWaypoint() && !doneWaiting){ 
    if(doneWaitingTimeout == undefined){ 
     setTimeOut(5000,function(){ 
     doneWaiting = true 
     doneWaitingTimeout = undefined 
     }) 
    } 
    } 
    ... 
}) 

这是我终于想出了解决方案:

function drawTrackTimeout() { 
    if(gData != null && gIndex < gData.length) { 
    var trains = []; 
    trains[0] = gData[gIndex]['train']; 
    removeTrain(trains); 
    drawTrack(gData[gIndex]['y1'], gData[gIndex]['x1'], gData[gIndex]['y2'], gData[gIndex]['x2'], '#FF0', trains); 

    statusFinalDest = gData[gIndex]['status_final_dest']; 
    if(statusFinalDest == 'ARRIVED') { 
     unloadCargo(); 
    } else if (gData[gIndex]['code'] == 'MOVE_TRAIN_AUTO' || gData[gIndex]['code'] == 'TURN_END') { 
     //moveTrainAuto(); 
    } else { 
     // handle error 
    } 
    gIndex++; 
    } else { 
    clearInterval(gIntid); 
    gIntid = null; 
    gData = null; 
    gIndex = 0; 
    } 
} 


function myEventMoveTrainManual(evt, performErrorCheck) { 
//debugger; 
     if(mutexMoveTrainManual == 'CONTINUE') { 
     var ajax = new Ajax(); 
     var param = {}; 
     if(evt) { 
      var cityId = evt.target.getParentNode().getId(); 
      var param = { "city_id": cityId }; 
     } 
     ajax.responseType = Ajax.JSON; 
     ajax.ondone = function(data) { 
      var actionPrompt = document.getElementById('action-prompt'); 
      actionPrompt.setInnerXHTML('<span><div id="action-text">'+ 
       'Train en route to final destination...</div></span>'); 
      gData = data; 
      gIndex = 0;    
      gIntid = setInterval(function(){drawTrackTimeout()},1000);    
     } 
     ajax.post(baseURL + '/turn/move-train-final-dest', param); 
     } 
}