2016-09-30 30 views
2

我已經創建了一個用戶在等待其他應用程序重新啓動時查看的html頁面。我創建了一個JavaScript腳本,它嚮應用程序發出多個請求,直到應用程序返回200.但是,當我嘗試打開我的html頁面時,瀏覽器崩潰。任何人都可以看到我的代碼有什麼問題:使用Javascript向服務器發送多個請求,直到服務器返回200

var responseStatus = 404; 
var numberOfTries = 0; 
var request = new XMLHttpRequest(); 
while(responseStatus != 200){ 
    console.log("Checking if restart has completed. Attempt number: " + numberOfTries); 
    request.open('GET', 'applicationurl', true); 
    request.onreadystatechange = function(){ 
     if (request.readyState === 4){ 
      console.log("Request Status: " + request.status); 
      responseStatus = request.status; 
      console.log("Response Status: " + request.status); 
      if (request.status != 200) { 
       numberOfTries++; 
       console.log("Restart has not yet completed! NumberOfTries: " + numberOfTries); 
      } 
     } 
    }; 
    request.send(); 
} 
console.log("Server has successfully restarted"); 
+5

放來延遲在你的代碼中使用的setTimeout方法, 你不斷打服務器,而這就是爲什麼你的瀏覽器簡單地crashe。 – Veer

+0

控制檯在第一次日誌之後不記錄任何內容。瀏覽器凍結,我需要強制退出並重新打開瀏覽器再次訪問html頁面。 – rurounisuikoden

+0

@rurounisergii再次,這是因爲你在一個循環中這樣做。實際上,如果不是成千上萬的請求,您將實際發送數百個請求,直到成功。即使這樣,即使你獲得了200回,你也可能事先發送數百個數據,因爲你不會等待它們返回並且它們都是異步發送的。 – vlaz

回答

1

您的方法發送多個請求,但它不會等待它們作出響應。

這裏是它如何工作的:

  • 一個XMLHttpRequest創建
  • 回調和數據分配給它
  • 該對象被髮送到服務器
  • 那麼while循環結束,再次運行,不等待回調運行

因此,很多o f XMLHttpRequest對象被創建並且許多請求同時運行,這不是您想要的。

你可以這樣做2種方式:

  • 包成一個功能,當它失敗時調用它(preferrable);
  • 設置一些間隔等待響應

1的方法:

function tryRequest(numAttempts) { 
    var responseStatus = 404; 
    var request = new XMLHttpRequest(); 

    console.log("Checking if restart has completed. Attempt number: " + numAttempts); 
    request.open('GET', 'applicationurl', true); 
    request.onreadystatechange = function(){ 
     if (request.readyState === 4){ 
      console.log("Request Status: " + request.status); 
      responseStatus = request.status; 
      console.log("Response Status: " + request.status); 
      if (request.status != 200) { 
       console.log("Restart has not yet completed! NumberOfTries: " + numAttempts); 
       tryRequest(numAttempts + 1) 
      } 
     } 
    }; 
    request.send(); 

    console.log("Server has successfully restarted"); 
} 
tryRequest(0); 

第二個辦法:

var responseStatus = 404; 
var numberOfTries = 0; 
var request = new XMLHttpRequest(); 
var interval = setInterval(tryRequest, 1000) 

function tryRequest() { 
    console.log("Checking if restart has completed. Attempt number: " + numberOfTries); 
    request.open('GET', 'applicationurl', true); 
    request.onreadystatechange = function(){ 
     if (request.readyState === 4){ 
      console.log("Request Status: " + request.status); 
      responseStatus = request.status; 
      console.log("Response Status: " + request.status); 
      if (request.status != 200) { 
       numberOfTries++; 
       console.log("Restart has not yet completed! NumberOfTries: " + numberOfTries); 
      } else { 
       clearInterval(interval); 
       console.log("Server has successfully restarted"); 
      } 
     } 
    }; 
    request.send(); 
    } 

} 

(聲明:我沒有測試兩者則)

+1

如果間隔方法仍處於打開狀態,則應該中止呼叫。 – epascarello

+0

@epascarello是的,你是對的,我會更新答案 – serge1peshcoff

0

您可以使用代碼,如

var responseStatus = 404; 
var numberOfTries = 0; 
function check(){ 
     var request = new XMLHttpRequest(); 
     console.log("Checking if restart has completed. Attempt number: " + numberOfTries); 
     request.open('GET', 'applicationurl', true); 
     request.onreadystatechange = function(){ 
      if (request.readyState === 4){ 
       console.log("Request Status: " + request.status); 
       responseStatus = request.status; 
       console.log("Response Status: " + request.status); 
       if (request.status != 200) { 
        numberOfTries++; 
        console.log("Restart has not yet completed! NumberOfTries: " + numberOfTries); 
        var tmp = setTimeout(function(){ check() },5000); // check after 5 second 
       } elseif (request.status == 200) { 
        console.log("Server has successfully restarted"); 
       } 
      } 
     }; 
     request.send(); 

    } 

//調用第一次

check(); 
3

最好的方式做到這一點(在我看來)是實際結合起來@ serge1peshcoff的兩個選項。將該呼叫寫爲一個函數,在響應失敗時自行調用,設置超時。對於大多數用途,您不希望在上一個請求之後立即發送另一個請求,您希望等待至少一秒或五秒以防止垃圾郵件服務器(您也沒有指出您期望的客戶端數量。對你的瀏覽器來說糟糕的是服務器可能很糟糕,即使在你的web應用程序完全啓動並返回200之前,服務器也可能處理請求)。

此外,setTimeout比setInterval更好,因爲您在每次往返時都明確地重置它。從@serge

借款:

function tryRequest(numTries) { 
    var responseStatus = 404; 
    var request = new XMLHttpRequest(); 
    numTries = numTries || 0; 

    console.log("Checking if restart has completed. Attempt number: " + numAttempts); 
    request.open('GET', 'applicationurl', true); 
    request.onreadystatechange = function(){ 
     numTries++ 

     if (request.readyState === 4){ 
      console.log("Request Status: " + request.status); 
      responseStatus = request.status; 
      console.log("Response Status: " + request.status); 
      if (request.status != 200) { 
       console.log("Restart has not yet completed! NumberOfTries: " + this.attempts); 
       setTimeout(tryRequest.bind(null, numTries), 5000); // five seconds 
      } 
     } 
    }; 
    request.send(); 

    console.log("Server has successfully restarted"); 
} 
tryRequest(); 
+0

爲什麼你不會將'numAttempts'作爲參數傳遞給'tryRequest'?在我看來,做'this.attempts = this.attempts || 0; this.attempts ++;'不起作用,因爲當你調用'setTimeout'時,你無需參數就將'tryAttempts'傳遞給它,並且每次都會重新創建this.attempts。 – serge1peshcoff

+0

如何在某個特定的函數退出後嘗試的數量? – rurounisuikoden

+0

更新了我的代碼,以解釋我通過傳入param來引入的'this'作用域問題。 @rurounisergii如果你想在經過一定次數的嘗試後退出,只需設置測試並返回,然後再次調用setTimeout。 – Paul