0

I have a worker thread that sends out a request to the server for data using an XMLHttpRequest. That request points to a php file that basically checks the current integrity of the information that the client has and if the client needs the new information then it is sent. Otherwise the server checks information until the client needs a response. After the server responds the whole process is repeated.

The problem arises when the browser realizes the script isn't responding and gives the user the option to stop the script. As you can see, this isn't the intended result. So what's the best way to continue using the comet-like structure without confusing the browser?

EDIT: I realized why the script is hanging, I repeated the whole worker thread instead of repeating the somewhere deeper inside the thread. So I guess my question now where to start the process again, after it finishes.

<?php
//Client sends their current id

if(isset($_GET['id']))
    $id = $_GET["id"];

//if id doesnt match servers id send them a new one
//other wise do not respond

$server_id = file_get_contents("ids.txt");

while($server_id == $id){
    $server_id = file_get_contents("ids.txt");
    sleep(1);
}
echo $server_id;
?>

Javascript:

self.addEventListener('message', function(e) {
var data = e.data;
switch (data.cmd) {
    case 'start':
  getInfo(data.id);
  self.postMessage('ID :: ' + response);

  break;
default:
  self.postMessage('Unknown command');
};
}, false);


var response = null;
var request = new XMLHttpRequest();

function getInfo(inputID){
    var url = "serverResponse.php?id=" + inputID;
    request.open("GET", url, false);
    request.onreadystatechange = updateState;
    request.send(null);
}

function updateState(){
    if(request.readyState == 4){
        if(request.status == 200){
            response = request.responseText;//getInfo(data.id);
        }
    }
}    

html:

<html>

<script type="text/javascript">

function sayHI() {
    var id = "666";
    worker.postMessage({'cmd': 'start', 'id' : id});
  }

var worker = new Worker('AjaxWorker.js');
worker.addEventListener('message', function(e){
    document.getElementById('result').textContent = e.data;
    //Some data has been received so go ahead and make another call to the server
    //This is where the script hangs because the worker waits for a response
    sayHI();
}, false);


</script>


<body>
<button type="button" name="submit" id="submit" onclick="sayHI()">Submit</button>        </br></br>
<output id="result" name="result">Result</output>

</body>


</html>
4

2 回答 2

1

您的线路:

request.open("GET", url, false);

async参数open()设置为false,这意味着 JavaScript 执行流在该 Ajax 调用上完全停止,直到它完成。在同步调用解决之前,您的网页将完全冻结,并且由于您使用的是长轮询,因此在很长一段时间内都不会发生这种情况。因此,您的浏览器解释器会向您发送一个警告,指出脚本执行需要很长时间。(这个警告也是完全合法的——在同步调用解决之前,你不能在你的页面上做任何事情。)

你需要使用request.open("GET", url, true);. 只需在 Ajax 调用之后移动需要发生的任何事情并将其放在onreadystatechange回调中。当服务器最终响应时,该updateState函数将触发。响应“彗星推送”(即通过来自服务器的响应解决长轮询查询)应该发生的任何事情都需要进入该回调。

异步 Ajax 将允许脚本继续执行并且不会导致您的 JS 解释器挂起。脚本流将直接通过它,而不是等待长轮询查询解决,并且稍后onreadystatechange将使用来自服务器的新信息调用回调。

编辑:

JavaScript 解释器只有一个线程。如果该线程长时间不间断地使用,浏览器将怀疑出现问题并发出警告。您的同步Ajax 调用会抓取单个 JS 线程,并且在服务器最终回复之前不会松手。正如我之前所说,在很长一段时间内,页面上不会发生任何其他事情。口译员被困在那个电话上。

使用同步 Ajax,您的流程如下所示:

send synchronous request
wait
and wait
and wait
(meanwhile, nothing else can get done)
and wait...
....
finally a response comes!
use the response to update the page

考虑这个优越的异步 Ajax 替代方案:

send ansyc request

[the interpreter sleeps and the browser is happy]

a response comes!
the request's readystatechange event fires now
the onreadystatechange handler uses the response to update the page

在第二个示例中,解释器可以休息一下,而不是等待 Ajax 请求解决。onreadystatechange每当 Ajax 调用从服务器返回时,您的处理程序函数就会被触发。如果您的调用是同步的,则解释器在调用解决之前什么都不做。如果你的调用是异步的,解释器可以自由地做它喜欢的任何事情——包括休息并且不会引起浏览器警告——直到调用解决并执行你的onreadystatechange处理程序。

于 2012-07-11T17:20:06.757 回答
0

你没有说你使用什么技术来实现反向 AJAX(HTTP 轮询?HTTP 流?WebSockets?其他东西?)如果你使用轮询,服务器应该及时响应,即使它“这里没有什么新鲜事” .

如果您保持连接打开,这可能会导致问题;HTTP 将浏览器限制为与服务器的两个同时连接。在这种情况下,浏览器和任何其他脚本只能使用一个连接;这可能会导致浏览器认为事情被阻止了。一个标准的方法是为彗星交互创建一个单独的主机名。

如果您使用 WebWorker,浏览器不会抱怨它被阻止。(但是,连接计数问题仍然可能导致问题。)

于 2012-07-11T16:56:02.457 回答