浏览器什么时候开始渲染部分传输的 HTML?
我有一个长期运行的报告,并希望在生成报告时向用户显示一个等待旋转器。我已经完成了这项工作,但不确定我是否以最好或正确的方式做这件事。
这是使用 ColdFusion,但我猜它可以是任何语言。在页面顶部,我有一些 Javascript (jQuery),它显示了一个等待旋转器,另外还有一个 documentReady 处理程序,我可以在其中将旋转器取下来。我刷新输出(如果重要的话),然后其余代码将处理报告内容。这并没有渲染旋转器,我推测,即使我在服务器上刷新东西,但一路上发生了一些缓冲,并且浏览器永远不会看到旋转器代码,直到为时已晚。因此,我在刷新吐出几百行 HTML 注释之前添加了一个循环。微调行数后,就成功了。我当时认为其他网站也是这样做的。
但是:今天,在观看我的另一个页面逐行吐出长期运行作业的状态时,我突然想到该页面会在每行之后刷新,并且浏览器会根据需要增量呈现该页面。这与我上面的结论不符,现在我不知道规则是什么。有没有可预测的方法来做到这一点?每个浏览器都有不同吗?
澄清:我很欣赏尝试解释等待旋转器的正确方法的答案,但我只是使用等待旋转器作为示例来说明我真正的问题:是否有可靠的方法来预测浏览器何时开始渲染HTML 是通过网络传输给他们的吗?通过观察可以明显看出,浏览器不会等待 /html 标签开始工作。这个问题不一定与Javascript有任何关系。例如,我描述的显示状态的第二页是纯 HTML。
I have a long-running report and want to show a wait-spinner to the user while it's generating. I have made this work already but am not sure I'm doing it the best or right way.
This is using ColdFusion but it could be any language I guess. At the top of the page, I have some Javascript (jQuery) that shows a wait-spinner plus there's a documentReady handler where I take the spinner down. I flush the output ( if it matters) and then the rest of the code works on the report contents. This wasn't ever rendering the spinner and I theorized that, even though I was flushing things on the server, some buffering was happening along the way and the browser never saw the spinner code until too late. So, I added a loop right before I flushed that spit out a few hundred lines of HTML comments. After fine-tuning the number of lines, that did the trick. I assumed then that that's how other sites did it too.
But: Today, while watching a different page of mine that spits out a line by line status of a long-running job, it occurred to me that that page flushes after each line and the browser renders that incrementally as desired. This doesn't match my conclusion from above and now I don't know what the rules are. Is there a predictable way to do this? Does it vary per browser?
CLARIFICATION: I appreciate the answers that attempt to explain the correct way to do a wait-spinner but I'm just using a wait-spinner as an example to illustrate my real question: are there reliable ways to predict when browsers will start to render HTML as it is streamed to them over the net? It's obvious through observation that browsers don't wait for the /html tag to start work. This question doesn't necessarily have anything to do with Javascript. For instance, that second page I describe that shows status is pure HTML.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
除了 Firefox 的内置延迟之外,还有其他区域会导致浏览器在渲染之前等待。
当 html 页面发送到浏览器时,它首先必须决定内容的去向,然后才能绘制屏幕。例如,表格因导致渲染延迟而臭名昭著。为了绘制表格,浏览器需要计算列大小。如果您使用百分比作为列宽或根本不指定它们,则浏览器必须在渲染之前获取整个表格。
但是,如果您使用诸如
table-layout:fixed;
css 属性之类的内容,那么浏览器只能读取第一行并在数据输入时开始绘制。其他标签可能会导致类似的问题。基本上,每当浏览器必须计算内容的大小时,它就必须渲染所有内容。如果您可以通过使用固定大小(宽度/高度)元素提前给出提示,那么浏览器不需要计算出任何内容,并且可以在下载元素时绘制它们。
作为一条自我强加的规则,我从不让浏览器决定任何事情。相反,我给元素固定大小。因此,我工作的网站通常具有闪电般的快速渲染速度。
Other than the built in delay for Firefox, there are other areas which cause the browser to wait before rendering.
As an html page is sent to the browser it first has to decide where things go before it can draw the screen. For example, tables are notorious for causing rendering delays. In order to draw a table the browser needs to compute column sizes. If you use percentages as column widths or don't specify them at all, then the browser has to get the entire table before rendering.
However, if you use something like the
table-layout: fixed;
css attribute then the browser can just read the first row and start drawing as data is fed to it.Other tags can cause similar issues. Basically any time the browser has to compute the size of content, then it has to have all of the content to render. If you can give it hints ahead of time through the use of fixed size (width/height) elements then the browser doesn't need to figure anything out and it can draw the elements as they are downloaded.
As a self-imposed rule, I never let the browser determine anything. Instead I give my elements fixed sizes. As a result the sites I work on usually have lightning fast rendering.
如果我理解正确,您希望在页面仍在加载内容时显示“正在加载”图像。
我所做的,以及我认为最好的方法是在页面顶部添加一个 div 标签,最接近保存加载图像/文本的 body 标签。您可以借助一些 css 将此 div 放置在其他位置。
然后让 Jquery 在页面加载时删除这个 div。我不会像某些人建议的那样使用 $(document).ready ,而是使用 $(window).load ,因为它是在整个页面完全加载时激活的,包括所有框架、对象和图像。
这里链接; http://4loc.wordpress.com/2009/04/28 /documentready-vs-windowload/
示例;
...
If I understand you correctly, you want a "loading"-image to display whilst page is still loading up content.
What I do, and what I believe is best way is to add a div-tag at top of your page, closest to body-tag which holds the loading image/text. You can place this div elsewhere with help of some css.
Then have Jquery remove this div when page is loaded. Instead of using $(document).ready as some have recommended i would use $(window).load instead, since it is activated when the complete page is fully loaded, including all frames, objects and images.
Se link here; http://4loc.wordpress.com/2009/04/28/documentready-vs-windowload/
Example;
...
--- 澄清后答案 ---
我原来的答案应该对某人有用(我希望),但这不是对问题的直接回答,所以我会发布另一个答案
对你重述的问题的回答是“否”。在FF的情况下,有一个预定义的初始渲染延迟,但其他浏览器会有所不同。 FF 渲染延迟也可以调整。
以 FF 为例,最初的 250 毫秒是 FF 在尝试第一次渲染之前至少找出一些有用信息的时间。然后,当它了解更多信息时,它会定期进行额外的渲染。
您无法确定浏览器何时开始呈现 HTML 文档。
--- 原始答案 ---
为了直接回答你的问题,我相信 Firefox 在对收到的第一个数据采取行动之前会等待 250 毫秒,但这可以改变。至于其他浏览器,我不知道。
但是,您不想走这条路。
当 jQuery 准备好发挥其魔力时,它会通过触发
$(document).ready()
让您知道>。在此之前,任何使用 jQuery 的尝试都将失败。换句话说,您的微调器没有显示,因为 jQuery 尚未准备好处理该请求。考虑以下示例,其中屏幕上显示两个占位符,我们将使用 jQuery 隐藏它们。
乍一看,
$("#one").hide();
似乎是多余的,但事实并非如此。$(".placeholder").hide();
在 jQuery 准备好之前调用,因此它没有任何效果,这就是为什么您会看到显示“Placeholder Two”(而不是“Placeholder One”) ") 如果您在网络浏览器中运行上面的标记。既然我们已经解决了这个问题,那么更大问题(“正确的方法”)的解决方案就是 AJAX。
$(document).ready()
的一部分运行。祝你好运!
--- Post-clarification Answer ---
My original answer should be useful to someone (I hope), but it isn't a direct response to the question, so I'll post another answer
The answer to your restated question is "no". In the case of FF, there is a predefined initial render delay, but other browsers will be different. That FF render delay can be tweaked as well.
Using FF as an example, those initial 250ms are time for FF to find out at least some useful information before attempting the first render. It then does additional renders periodically as it learns more.
There is no way for you to determine when the browser has started to render the HTML document.
--- Original Answer ---
To directly answer your question, I believe Firefox waits 250ms before acting on the first data received, but that can be changed. For other browsers, I don't know.
However, you don't want to go that route.
When jQuery is ready to work its magic, it'll let you know by firing
$(document).ready()
. Before then, any attempt to use jQuery will fail. In other words, your spinner isn't showing up because jQuery isn't ready to process that request yet.Consider the following example, where two placeholders are shown on-screen, and we'll use jQuery to hide them.
It may appear at first that
$("#one").hide();
is redundant, but that's not true.$(".placeholder").hide();
is called before jQuery is ready, so it has no effect, which is why you'll see "Placeholder Two" displayed (and not "Placeholder One") if you run the markup above in a web browser.Now that we have that out of the way, the solution to the larger problem (the "right way") is AJAX.
$(document).ready()
.Good luck!
我预计它会因浏览器而异:有些会在页面完全接收之前开始渲染;有些会在页面完全接收之前开始渲染;其他人会在开始之前等待整个 html 文件。
我注意到 HTTP 响应规范提供了一个“206 Partial Content”标头,这可能为值得研究的跨浏览器解决方案带来一些希望。
几乎可以肯定有很多方法可以剪切它,但我的直接想法是提供存根页面,然后使用 ajax 按需拉取和渲染片段。例如,许多大型网站似乎最初提供的是最小视图,然后如果您向下滚动得足够多,它会触发 ajax 请求来检索更多数据并将其附加到页面。例如:facebook、slashdot。
我无法想象这太难实施了;即使采用冷融合。当您触发 ajax 请求时启动微调器,并在调用回调时停止它。
I expect it will vary by browser: some will start to render before the page is completely received; others will wait for the whole html file before starting.
I note that the HTTP Response specification provides a "206 Partial Content" header which might offer some hope for a cross-browser solution which is worth looking into.
There's almost certainly a number of ways to cut it, but my immediate idea would be to deliver the stub page, then use ajax to pull and render the fragments on demand. eg a lot of big sites seem to be delivering a minimal view initally, then if you scroll down enough it fires an ajax request to retrieve more data and append it to the page. eg: facebook, slashdot.
I can't imagine this being too hard to implement; even with coldfusion. You start the spinner when you fire the ajax request and stop it when the callback is invoked.