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

28
为了让IM客户端一直保持登录状态,Facebook使用AJAX在将页面插入文档之前加载页面,避免了完整的页面加载。
然而,在Facebook的AJAX请求期间,浏览器似乎正在可见地加载;刷新按钮变为X,并且内置于浏览器中的进度指示器显示加载/等待等。
我已经成功实现了基于AJAX的导航,但我的浏览器没有显示任何加载指示(因为请求是异步的)。 Facebook如何做到这一点?

始终保持IM客户端登录状态,即使在新标签页中打开链接,IM也会保持相同的状态... - feeela
3个回答

24

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

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

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


1
感谢您的深入回答。然而,当我尝试这种方法(创建一个script标签,将其src设置为我的JSON控制器,将其附加到我的headbody标签中)时,浏览器没有显示加载指示器。结果成功返回,并且我在页面源代码中看到了添加的脚本标记。此外,我已经在我的服务器端方法中添加了Sleep方法来模拟长时间运行的过程,以查看加载是否出现。但是仍然没有成功。有什么想法吗? - Kamyar
2
提示:当我使用 IFrame 时,一切都很正常。但是无法使用 script 标签。 - Kamyar
@Kamyar 我其实不确定。我前段时间回来尝试自己做这个,但遇到了你所描述的同样问题。我很确定当我写这个答案时它是可以工作的...我不确定是否有什么改变或者我在这里犯了错误。 - Jeremy
这真让我抓狂!不知道他们是怎么做到的。如果你找到了什么,请在这里分享一下,我会非常感激。我现在已经没有任何想法了。 - Kamyar
他们使用iframe来实现一些应该“感觉”像页面加载的东西(如果您在触发“页面”加载时检查页面,您会短暂地看到一个“iframe_transport” iframe出现在文档底部,然后被删除)。值得注意的是,这种方法并不适用于所有浏览器。在Safari中尝试一下,当您从您的动态消息源导航到您的个人主页时,您不会看到任何指示页面正在加载的迹象,就像在Chrome等浏览器中那样。 - Dtipson

11

Facebook使用他们开发的一个工具,叫做Big Pipe,将网站内容分块流式传输给客户端。他们会发送一个带有DOM结构的基础script标签给客户端,然后以异步方式加载页面上的模块,这样客户端就可以展示模块1,而服务器则在获取模块2,从而提高了加载速度。

除此之外,他们还使用了一种叫做“长轮询”的技术。通过HTTP 1.1,他们利用持久连接,不必担心超时。当页面被渲染时,客户端脚本向Facebook发出一个AJAX请求,从本质上来说是“监听”事件。它将一直保持监听,直到事件发生。同时,浏览器将显示正在“加载”数据。

当Facebook端触发事件(比如有人在你的墙上发表评论),FB将把响应发送回客户端以触发相应的回调(比如弹出小提示通知你有评论),并立即向FB发送另一个请求以监听下一个事件。


4
Facebook使用iframe来通信,当他们想要浏览器显示“繁忙”状态时。您可以使用iframes通过让iframe调用父窗口中的函数来进行跨域ajax。

1
请注意,iframe加载是否触发浏览器的繁忙指示器完全取决于浏览器。 Safari和后来的IE选择抑制这些指示器用于iframes(在我看来对用户来说是愚蠢/障碍,但它确实通过减少触发繁忙状态的事物使他们的浏览器“看起来”更快),因此即使使用该技术也无法解决问题。 - Dtipson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接