【问题标题】:Use Javascript to send multiple requests to server until server returns 200使用 Javascript 向服务器发送多个请求,直到服务器返回 200
【发布时间】:2017-02-08 23:36:48
【问题描述】:

我创建了一个 html 页面,用户在等待另一个应用程序重新启动时查看该页面。我创建了一个 javascript 脚本,它向应用程序发出多个请求,直到应用程序返回 200。但是,当我尝试打开我的 html 页面时,浏览器只是崩溃了。谁能看到我的代码有什么问题:

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");

【问题讨论】:

  • 使用 setTimeout 方法在你的代码中设置延迟,你不断地访问服务器,而这就是你的浏览器崩溃的原因。
  • 控制台在第一次登录后不记录任何内容。浏览器死机,我需要强制退出并重新打开浏览器才能再次访问 html 页面。
  • @rurounisergii 再次,这是因为您正在循环执行此操作。实际上,在一个成功之前,您将发送数百甚至数千个请求。即便如此,即使您确实收到了 200 个回复,您也可能会提前发送数百个,因为您不会等待他们返回并且它们都是异步发送的。
  • 自己进行 DDoS 的好方法。并且在异步调用中使用 while 循环是行不通的。

标签: javascript html ajax server restart


【解决方案1】:

您的方法发送多个请求,但它不会等待它们响应。

这是它的工作原理:

  • XMLHttpRequest 已创建
  • 一个回调和一个数据分配给它
  • 这个对象被发送到服务器
  • 然后while 循环结束并再次运行,而不是等待回调运行

结果创建了很多XMLHttpRequest对象,同时运行了很多请求,这不是你想要的。

您可以通过两种方式做到这一点:

  • 将其包装到一个函数中,并在它失败时调用它(首选);
  • 设置等待响应的时间间隔

第一种方法:

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();
  }

}

(免责声明:当时我没有测试两者)

【讨论】:

  • interval 方法如果仍然打开,应该中止调用。
  • @epascarello 是的,你说得对,我会更新答案
【解决方案2】:

你可以像这样使用代码

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();
    

    【讨论】:

    • 为什么不将numAttempts 作为参数传递给tryRequest?在我看来,做this.attempts = this.attempts || 0; this.attempts++; 是行不通的,因为当你调用setTimeout 时,你将tryAttempts 不带参数地传递给它,并且每次都会重新创建this.attempts
    • 在尝试一定次数后如何让函数退出?
    • 更新了我的代码以解决我通过传入参数引入的this 范围问题。 @rurounisergii 如果您想在尝试一定次数后退出,只需设置测试并在再次调用 setTimeout 之前返回。
    猜你喜欢
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多