Facebook 如何在 AJAX 页面加载期间显示浏览器加载进度?

Posted

技术标签:

【中文标题】Facebook 如何在 AJAX 页面加载期间显示浏览器加载进度?【英文标题】:How does Facebook show browser loading progress during AJAX Page Loads? 【发布时间】:2012-02-13 12:07:25 【问题描述】:

为了让 IM 客户端始终保持登录状态,Facebook 通过使用 AJAX 在将其插入文档之前加载其页面来避免整个页面加载。

但是,在 Facebook AJAX 请求期间,浏览器似乎正在加载;重新加载按钮变为 X,浏览器内置的进度指示器指示加载/等待等)

我已经能够成功实现基于 AJAX 的导航,但是我的浏览器没有显示任何加载指示(因为请求是异步的)Facebook 是如何做到的?

【问题讨论】:

"保持 IM 客户端始终登录" IM 保持相同的状态,即使在新标签页中打开链接... 【参考方案1】:

Facebook 使用他们开发的名为 Big Pipe 的工具,基本上将他们的网站分块流式传输到客户端。他们向客户端发送带有裸 DOM 的初始脚本标记,并且脚本在页面上异步加载模块 - 想法是客户端在服务器获取模块 2 时呈现模块 1,因此缩短了加载时间。

最重要的是,他们使用了一种称为长轮询的技术。使用 HTTP 1.1,他们可以利用持久连接而不必担心超时。呈现页面时,客户端脚本向 Facebook 发出 AJAX 请求,以“侦听”事件。它会坐在那里听,直到事件发生。与此同时,浏览器似乎正在“加载”数据。

当 Facebook 端触发事件时(比如有人在您的留言板上发表评论),FB 会将该响应发送回客户端以触发相应的回调(例如弹出一个小工具提示,让您知道该评论) 并立即向 FB 发送另一个请求以监听下一个事件。

【讨论】:

【参考方案2】:

Facebook 在希望显示浏览器“忙碌”状态时使用 iframe 进行通信。 通过在父窗口中调用 iframe 函数,您可以使用 iframe 进行跨域 ajax。

【讨论】:

请注意,iframe 加载是否触发浏览器的忙指示符完全取决于浏览器。 Safari 和后来的 IE 选择抑制 iframe 的这些指示符(恕我直言,这对用户来说是愚蠢的/bar,但它肯定会使他们的浏览器“出现”得更快,因为触发繁忙状态的东西更少)所以即使这种技术也行不通。 【参考方案3】:

当文档中有元素正在加载时,浏览器会显示加载状态。 Ajax 请求完全由 javascript 发出;文档不受影响,因此不会触发加载状态。

另一方面,Facebook 的大多数请求都是通过在文档中插入一个<script> 标签来发出的,指向一个包含他们想要的数据的 JavaScript 文件。 (本质上是 JSONP,除了它们使用不同的格式。)浏览器将显示其加载状态,因为 <script> 标记是文档中未加载的元素。

如果您不小心,这种技术/JSONP 可能会使您的站点面临安全风险,因为允许跨站点请求。 Facebook 通过为每个资源生成随机 URL 来处理这个问题,这些 URL 在初始页面加载时发送到浏览器。

【讨论】:

感谢您富有洞察力的回答。但是,当我尝试这种方法时(创建一个script 标记,将其src 设置为我的JSON 控制器,将其附加到我的headbody 标记,浏览器不显示加载指示器。结果回来了成功,我在页面源代码中看到添加的脚本标签。此外,我在服务器端方法中添加了Sleep 方法以模拟长时间运行的过程,以查看加载出现。但仍然没有运气。有什么想法吗?跨度> 附言。当我使用IFrame 时,一切正常。但不能使用script 标签。 @Kamyar 我实际上不确定。不久前,我回来并尝试自己再次执行此操作,并且遇到了与您描述的相同的问题。我很确定当我写这个答案时它正在工作......我不确定是否有什么改变或者我在这里有什么问题。 这快把我逼疯了!不知道他们是怎么做到的。如果您在找到任何东西时在这里分享它,我将不胜感激。我目前没有想法。 他们将 iframe 用于应该“感觉”像页面加载的内容(如果您在触发“页面”加载时检查页面,您可以短暂地看到“iframe_transport”iframe 出现在底部文件,然后被删除)。值得注意的是,这种方法不适用于所有浏览器。在 Safari 中尝试一下,当您从提要导航到墙上时,您不会看到任何页面正在加载的迹象,就像在 Chrome 等浏览器上所做的那样。

以上是关于Facebook 如何在 AJAX 页面加载期间显示浏览器加载进度?的主要内容,如果未能解决你的问题,请参考以下文章

Facebook 与 AJAX 元标记共享

使用量角器在页面加载期间阻止第三方URL

当用户到达页面末尾以加载新内容时,如何调用 JavaScript (AJAX) 函数?

Ajax加载页面如何刷新地址栏URL的问题

如何在使用 Pace.JS 加载期间显示 Div

如何在我的 SPA 的特定页面上隐藏 Facebook 客户聊天插件?