代码之家  ›  专栏  ›  技术社区  ›  Jaka Jančar

加载comet/server push xmlhttprequest时,停止浏览器__tomber of doom__

  •  7
  • Jaka Jančar  · 技术社区  · 15 年前

    (这个问题类似于 this one ,但它是用于使用xmlhttpRequest,而不是用于Comet的iframe。)

    我正在启动一个异步长轮询,如下所示:

    var xhr = new XMLHttpRequest();
    xhr.open('POST', url);
    xhr.send();
    

    如果我在里面做这个 <script>...</script> 在头中,它将使文档永远保持加载状态。(我正在Mac OS X和iPhone上的Safari中测试,这是我唯一需要支持的浏览器)。

    使用 DOMContentLoaded load 事件不起作用。

    使用设置超时 足够大 拖延会奏效的。0不会,1000会,100会有时不会。我对这个感到不舒服。

    我发现唯一可行的方法是两者的结合:

    document.addEventListener('DOMContentLoaded', function () {
        setTimeout(function () {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', url);
            xhr.send();
        }, 0);
    });
    

    我想这暂时解决了问题,但我仍然担心将来会坏。 //编辑:这也不可靠。

    有人知道更可靠的方法吗?

    4 回复  |  直到 15 年前
        1
  •  2
  •   Keith    15 年前

    我不确定,但如果浏览器显示它仍在下载,那么这是完全正确的-这基本上不是什么彗星编程?服务器仍在发送未缓冲的内容,当该内容在一个javascript块中传输时,服务器就可以将事件推送到客户机浏览器。

    在Ajax早期(例如在IE6中 XMLHttpRequest 是一个单独的ActiveX对象)我希望浏览器不知道它还在等待。

    但在Safari 4、Chrome、FX3.5和所有现代浏览器中, 对象 是内置的-它知道它仍在等待服务器继续流式传输其内容,就像它与和 <IFrame>

    简而言之,我希望任何Comet方法都能显示浏览器仍然在下载,因为它是。我希望您找到的任何解决方案在将来的构建中都能得到修复,因为Comet本质上是一个让服务器推送模型工作的黑客。

    然而,他们已经开始在HTML5中构建真正的服务器推送支持。

    移动WebKit是否支持 HTML 5 draft event-source 标签?如果是这样的话,你可以尝试一下。

    然后你会得到这样的东西:

    <!-- new HTML 5 tag supporting server-push -->
    <event-source src="http://myPushService.com" id="service">
    
    <script type="text/javascript">
    
        function handleServiceEvent(event) {
            // do stuff
        }
    
        // tell browser to fire handleServiceEvent in response to server-push
        document.getElementById('service').addEventListener('event name', handleServiceEvent, false);
    </script>
    
        2
  •  1
  •   Matt    15 年前

    当你说:

    …这将导致文档永久地继续加载。

    你说这个到底是什么意思?你的意思是进度条永远不会结束吗?或者实际文档甚至不完全可见?Ajax请求不太可能阻止整个文档的加载,但无论如何…

    案例1:进度条永远不会结束

    这可能是由于Ajax请求从未完成造成的。你试过在Firebug控制台中查看Ajax请求吗?它将向您显示所做的请求和服务器的响应。我从这里开始只是为了确保服务器正在发送 某物 后退。

    案例2:文档元素没有完全加载/可见

    您可以尝试将<script>标记放在</body>标记之前。

    当你这样做的时候, 在脚本执行之前完全加载,您不必等待“domready”或“onload”启动。另外,请记住 加载并不意味着DOM 内容 (例如图像)已完全加载(您需要等待“onload”以确保这一点)

    无论哪种情况,我都会尝试将脚本放在</body>标记之前,这样就有机会构建DOM骨架。

    边注:

    您是否使用任何类型的调试器查看页面?(Firebug,WebKit检查员)。如果您打开了控制台,并且遇到了一个javascript错误,Webkit检查器尤其会停止处理整个文档。您在控制台中看到任何javascript错误吗?如果关闭调试程序,页面是否加载?

        3
  •  0
  •   dutchflyboy    15 年前

    可以尝试使用加载事件而不是domcontentloaded事件吗?它应该有所不同,因为只有在页面完全加载时才调用它。

    var xhr;
    document.addEventListener('load', function () {
        xhr = new XMLHttpRequest();
        xhr.open('POST', url);
        xhr.send();
    });
    

    这应该有效。但是,我不经常使用彗星,所以目前我没有任何方法来测试它。

    编辑:对不起,刚才看到马特已经说过了。

        4
  •  0
  •   RMorrisey    15 年前

    在某些浏览器中,如果没有指定第三个参数,open(…)方法默认情况下会同步发送Ajax请求?尝试:

    xhr.open('POST', url, true);
    

    使调用显式异步。