2016-09-30 81 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