2010-07-26 5 views
1

나는 내가 작성한 페이스 북 게임을위한 새로운 기능을 연구하고 있습니다. 게임을 통해 플레이어는 유럽의 도시를 여행하고 수익을 위해 물품을 배달 할 수 있습니다. 내가 추가하고있는이 기능은 길 찾기 AI를 게임에 추가합니다. 플레이어가 이동할 도시를 선택할 수있게되면 게임은 시작 도시에서 목적지 도시까지 플레이어의 기차를 자동으로 이동시킵니다. 나는 AJAX와 setTimeout()을 사용하여 백엔드에서 데이터를 가져와 도시를 연결하는 트랙을 따라 열차의 움직임을 가능하게하고있다. (의도적으로) 내가하려고하는 것을 더 잘 이해할 수있는 코드를 참조하십시오.AJAX 요청을 동기화하려고 시도했습니다.

문제는 setTimeout()이 너무 자주 호출되는 것입니다. 나는 statusFinalDest라는 전역 변수를 두 었는데, ENROUTE와 ARRIVED 두 값을 가질 수 있습니다. 열차가 ENROUTE 인 동안 JS 열차 이동 함수는 백엔드가 ARRIVED의 statusFinalDest를 반환 할 때까지 setTimeout을 사용하여 자체 호출합니다.이 시간이 지나면 기차 이동 시간 초과 루프가 (아마도) 종료됩니다. 그러나 myEventMoveTrainManual()을 백엔드 프로세스마다 한 번씩 호출하는 대신 statusFinalDest의 변경된 상태를 인식하지 않는 것처럼 매우 자주 호출됩니다. 이 과도한 행동을 끝내기 위해 코드에 제한 구조를 추가하려고 시도했지만 작동하지 않는 것으로 보입니다.

가 여기에 해당 FBJS의 (페이스 북 JS) 코드 : 여기

function myEventMoveTrainManual(evt) { 
     if(mutexMoveTrainManual == 'CONTINUE') { 
     //mutexMoveTrainManual = 'LOCKED'; 
     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) { 
      statusFinalDest = data.status_final_dest; 
      if(data.code != 'ERROR_FINAL_DEST') { 

      // Draw train at new location 
      trackAjax = new Ajax(); 
      trackAjax.responseType = Ajax.JSON; 
      trackAjax.ondone = function(trackData) { 
       var trains = []; 
       trains[0] = trackData.train; 
       removeTrain(trains); 
       drawTrack(trackData.y1, trackData.x1, trackData.y2, trackData.x2, '#FF0', trains); 

       if(data.code == 'UNLOAD_CARGO') { 
       unloadCargo(); 
       } else if (data.code == 'MOVE_TRAIN_AUTO' || data.code == 'TURN_END') { 
       moveTrainAuto(); 
       } else { 
       /* handle error */ 
       } 
       mutexMoveTrainManual = 'CONTINUE'; 
      } 
      trackAjax.post(baseURL + '/turn/get-track-data'); 
      } 
     } 
     ajax.post(baseURL + '/turn/move-train-set-destination', param); 
     } 

     // If we still haven't ARRIVED at our final destination, we are ENROUTE so continue 
     // moving the train until final destination is reached 
     // statusFinalDest is a global var 
     if(statusFinalDest == 'ENROUTE') { 
     setTimeout(myEventMoveTrainManual, 1000); 
     } 
} 

그리고 백엔드 PHP 코드 : 함수 myEventMoveTrainManual이 이벤트 핸들러에서 호출되는 경우

public function moveTrainSetDestinationAction() { 
    require_once 'Train.php'; 
    $trainModel = new Train(); 

    $userNamespace = new Zend_Session_Namespace('User'); 
    $gameNamespace = new Zend_Session_Namespace('Game'); 

    $this->_helper->layout()->disableLayout(); 
    $this->_helper->viewRenderer->setNoRender(); 

    $trainRow = $trainModel->getTrain($userNamespace->gamePlayerId); 
    $statusFinalDest = $trainRow['status_final_dest']; 
    if($statusFinalDest == 'ARRIVED') { 
     $originCityId = $trainRow['dest_city_id']; 
     $destCityId = $this->getRequest()->getPost('city_id'); 
     if(empty($destCityId)) { 
     // If we arrived at final dest but user supplied no city then this method got called 
     // incorrectly so return an error 
     echo Zend_Json::encode(array('code' => 'ERROR_FINAL_DEST', 'status_final_dest' => $statusFinalDest)); 
     exit; 
     } 

     $gameNamespace->itinerary = $this->_helper->getTrainItinerary($originCityId, $destCityId); 
     array_shift($gameNamespace->itinerary); //shift-off the current train city location 
     $trainModel->setStatusFinalDest('ENROUTE', $userNamespace->gamePlayerId); 
     $statusFinalDest = 'ENROUTE'; 
    } 
    $cityId = $trainRow['dest_city_id']; 
    if($trainRow['status'] == 'ARRIVED') { 
     if(count($gameNamespace->itinerary) > 0) { 
     $cityId = array_shift($gameNamespace->itinerary); 
     } 
    } 
    $trainRow = $this->_helper->moveTrain($cityId); 
    if(count($trainRow) > 0) { 
     if($trainRow['status'] == 'ARRIVED') { 
     // If there are no further cities on the itinerary, we have arrived at our final destination 
     if(count($gameNamespace->itinerary) == 0) { 
      $trainModel->setStatusFinalDest('ARRIVED', $userNamespace->gamePlayerId); 
      $statusFinalDest = 'ARRIVED'; 
     } 
     echo Zend_Json::encode(array('code' => 'UNLOAD_CARGO', 'status_final_dest' => $statusFinalDest)); 
     exit; 
     // Pass id for last city user selected so we can return user to previous map scroll postion 
     } else if($trainRow['track_units_remaining'] > 0) { 
     echo Zend_Json::encode(array('code' => 'MOVE_TRAIN_AUTO', 'status_final_dest' => $statusFinalDest)); 
     exit; 
     } else { /* Turn has ended */ 
     echo Zend_Json::encode(array('code' => 'TURN_END', 'status_final_dest' => $statusFinalDest)); 
     exit; 
     } 
    } 
    echo Zend_Json::encode(array('code' => 'MOVE_TRAIN_AUTO_ERROR')); 
    } 
+0

혼란스러운 점을 명확히하기 위해 myEventMoveTrainManual()은 이벤트 핸들러가 아니지만 이벤트 핸들러에서 호출됩니다. –

답변

2

, 당신 ' 이벤트가 발생할 때마다 새로운 타이머가 실행되게됩니다.

은 도움이

하나의 간단한 해킹은 새로운 시작하기 전에 타이머를 죽일 것입니다 :

var timerId; 

//... 
clearTimeout(timerId); 
timerId = setTimeout(myEventMoveTrainManual, 1000); 
//... 

을하지만 난 당신이 정말로 다른 기능, 당신의 타이머 루프 경우 검사 하나를 호출되어 수행 할 작업을 생각한다 이미 실행 중이며 그렇지 않으면 myEventMoveTrainManual을 호출합니다.

+0

신속하게 응답 해 주셔서 감사합니다. 나는 내 코드에 clearTimeout()을 추가했다. 그것은 일을 개선했지만 내 주요 문제를 해결하지 못했습니다. 이제 나는 또 다른 문제가 있다는 것을 깨달았다. 이러한 과도한 함수 호출은 모두 turnEnd()를 너무 자주 호출하여 내 차례 횟수를 과장하고있다. 이것은 심각한 문제입니다. 어쨌든, 도와 줘서 고마워. –

관련 문제