关于Mobile Ajax 和 Frost Ajax 库
?
Ajax: 基于 JavaScript/ECMAScript 的客户端技术,提供客户端和服务器间的异步通信 (你可以重载网页的部分内容,而不需要刷新完整网页)。Ajax 是一个复杂的技术,包括数据的获取、操作和显示。 Mobile Ajax: Mobile Ajax 是上述两个概念的组合。Mobile Ajax 与桌面电脑 Ajax 是相同的技术。但两者略有不同:不同的移动设备浏览器有不同功能;网络和设备的性能有限;用户和设备交互能力有限。Ajax 可用于改进移动互联网,如Ajax可以帮助解决低带宽和易用性问题——Ajax 可以只重载网页必要部分,这就保证了更快的载入速度;而且想象有一个挺长的需要下翻页的页面,通过 Ajax 获取信息并立刻显示,用户就不必重新翻动页面;如果采用页面重载的话,用户不得不一次次重新翻动页面。
从2006年[2]开始,Mobile Ajax 引起了很多关注[3] ,越来越多的人对此感兴趣。关于此问题有大量的会议和博客文章,如 W3C/OpenAjax Alliance-组织的讨论会[4],OpenAjax Alliance Mobile Ajax Task-force [5]等。
撇开 Mobile Ajax 的争议和其局限性不谈,Mobile Ajax 是能提高移动互联网用户使用体验的工具之一。由于不同的浏览器的能力不同,其 JavaScript 实现也不同,Mobile Ajax 被分成了许多碎片。因此很难和其他移动互联网技术相比较,就像比较桔子和苹果一样。
Mobile Ajax 常被用来指包含可安装的程序的技术,此程序通常是用 Java/J2ME 开发的可以执行 JavaScript 和生成 HTML 的程序。这些技术常被用作实现 widget 引擎和让开发者可通过 Web 标准创建能运行在设备上的应用程序。 尽管他们不称自己为 Web 浏览器,而是称为 framework 或 platform.。Mojax[6] 和已遭弃用的 Opera Platform [7] 就是很好的例子。
浏览器局限性和其他问题让我们来看看移动设备的浏览器有哪些局限性。下面列举了所有主要的移动设备浏览器。WML 浏览器已经不再流行,我们只考察能显示 XHTML/WAP 2.0 的浏览器[8]:
Pocket IE/IE Mobile (WM 2003, 5.0, 6.0) OpenWave (>= Mercury) Access Netfront (>= 3.4) Nokia S60 Minimo (Mozilla) Opera Mini 和类似产品 (基于代理)所有上述浏览器都或多或少的支持部分 Ajax ,或者其未来版本承诺支持 Ajax 。"部分" Ajax 的含义是浏览器和 JavaScript 引擎可以执行异步服务器调用。但由于 Ajax 是很复杂的技术,而且缺少标准支持和 DOM 功能,不同浏览器的 Ajax 实现差异较大。
Opera Mobile 是真正的移动设备浏览器,因为其不受上述限制并提供完全的 JavaScript 实现。
要处理 Ajax,移动设备浏览器需要支持以下特性:
- 异步发送/接收数据 (通过 XMLHttpRequest 对象或者 ActiveX) 数据到达后可以理解执行某些操作 (通常通过回调函数) 在客户端显示收到的数据
第三点需要 DOM 函数以进行文档操作。受限的浏览器常缺少足够的 DOM 实现,只能实现 DOM 规范的一部分。另一个可能性是使用非标准的但很流行的 innerHTML,也可用于在客户端中修改网页的部分内容。在移动互联网中 innerHTML 常常是唯一的可行方案。为了使用 innerHTML ,你需要使用另一个 DOM 函数—— getElementById()
。幸运的是大部分浏览器都支持此 DOM 功能。我在过去的开发中发现如果浏览器实现了 XHR 那一般也支持 getElementById()
。
另一个移动互联网中的大问题是网络延迟,此问题不光是 Mobile Ajax 有,其他移动互联网技术都受此问题困扰。无线网络可能有严重的网络延迟问题,有时长达数秒。这意味着你向服务器发出请求后,可能要数秒之后才能下载数据。使用 Ajax 可以克服其他问题,如上面所提到的降低网络流量和提高较长网页的易用性。但网络延迟问题对 Mobile Ajax 来说是一个严重的问题。幸运的是随着网络和移动设备的性能越来越高,这些问题都在渐渐消失。
在受限浏览器中运行Ajax让我们来看看实际例子——我将从一个基本 Ajax 请求开示。任务是在用户点击链接后请求服务器端脚本——服务器端脚本的返回数据应被显示在链接下方。下面是标记代码:
<a href="no_ajax.html" onclick="return !getData();">request data</a><div id="datacontainer">data should go here</div>
上面的代码包含链接和将用于接受数据的容器。链接的 onclick
属性包含 JavaScript 代码:调用函数,并返回取反后的函数返回值。此返回值的作用是保证无论浏览器是否支持Ajax,用户都能看到链接的内容;如果支持Ajax,则将在同一页显示链接内容,用户得到更好的使用体验:
getData()
返回 true
(表示成功) 则链接的 onclick
返回 false
,导致点击链接操作被中止,浏览器也不会继续跳转到 href
属性所指页面。 如果 getData()
返回 false
(如碰到无法找到某 JavaScript 方法) 则 onclick
属性返回 "true" ,将导致继续访问链接页面,就如同 onclick
属性不存在一样。 上面的技巧和下面的部分 JavaScript 代码来自一本很好的书:"Bulletproof Ajax" 作者是Jeremy Keith[9]。getData()
函数如下:
function getData() { var xhr = false; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else if (window.ActiveXObject) { try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) { xhr = false; } } } if(xhr) { xhr.onreadystatechange = function() { parseResponse(xhr); }; xhr.open("GET", "somescript.php", true); xhr.send(null); document.getElementById("datacontainer").innerHTML = "...loading..."; return true; } else { return false; }}
每当 xhr
对象的 onreadystatechange
属性改变时,getData()
调用 parseResponse()
(此乃回调函数)。getData()
返回 true
或 false
,决定是否执行链接。parseResponse()
然后通过 innerHTML 将获取的数据放入容器中。代码如下:
function parseResponse(request) { if (request.readyState == 4) { if (request.status == 200 || request.status == 304) { var data = request.responseText; document.getElementById("datacontainer").innerHTML = data; } }}
这是很基本的使用 Ajax 的方式。其优点是很多能支持 Ajax 的设备上都可以运行此代码,即使手持设备也可以。这里要求 XHR/ActiveX, getElementById()
和 innerHTML —— 这也正是 Frost 库的核心。下面将讨论 Frost 库。
Frost Ajax 库用于在受限浏览器上实现 Ajax 开发,如在手机和手持游戏机上。Frost 提供可用于开发 Ajax Web 应用程序的 JavaScript 函数。底层的实现力求功能最简,文件大小最小。Frost 的目标是只输出目标浏览器能运行的 JavaScript 代码,也就说需要服务器端浏览器探测。Frost 服务器端目前已有 PHP 版本,很多人都希望将其移植到 Java 和 Ruby 中。
Frost 使用方法很简单:
在你的页面中引入 Frost ,常用script
标记的 src
属性 (指向服务器端脚本) 在你的标记代码或脚本代码中加入一些 Frost 函数 (见下例) 客户端浏览器请求页面时,Frost 尝试检测用户浏览器 根据浏览器的能力 Frost 输出相应的 JavaScript 代码 如果浏览器不支持所需 Ajax 功能,Frost 函数返回 false,这时可以执行备用函数 如果 Frost 无法识别浏览器或无法获取浏览器能力,将输出通用版本 Frost 对已知浏览器输出很少量代码;对未知浏览器将输出较多更健壮的代码。
Frost 由核心库构成。使用时可以设置包含哪些组件。由于 Frost 包含服务器端组件,可以引用 Frost 网站上的脚本文件或在你的服务器中安装服务器端程序(你可以控制浏览器检测)——这种情况你可以直接在 XHTML 文档中引入库的 JavaScript 输出,以解决网络延迟问题。
Frost 目前仍在开发中并未被官方发布。你可以在 http://frostlib.org 中下载 pre-release 版。欢迎使用反馈。
重新回到刚才提到的 Ajax 例子,如果你想用 Frost Ajax 库,那代码可能如下所示:
<a href="no_ajax.html" onclick="return !f('urltoid',['somescript.php', 'datacontainer2']);">request data</a><div id="datacontainer">data should go here</div>
这代码似乎并刚才还多,但是通用性更强。f()
函数是 Frost 提供的唯一公开函数,封装了所有 Frost 函数。此函数的参数是 Frost 函数名和此函数的参数数组,这里是 urltoid
和用于显示数据的容器的 id
。f()
返回 true
或 false
,如果发生错误,浏览器可以显示链接 href
页面。
可以在手机浏览器中访问 http://frostlib.org/demo/ 查看其实际效果——此页包含此例子的两个版本并显示 Frost 调试结果。此网页在全功能手机浏览器如 Opera Mobile 中能正常工作,在受限手机浏览器如 Opera Mini 4, IE 和 Minimo 中也能工作——所有浏览器测试都基于 Windows Mobile 5。在 PlayStation 3 和 Wii 浏览器中也能正常工作。
Frost 调试输出信息显示了库的工作过程。这些输出信息能帮助开发者调试,因为在手机中很难调试 JavaScript 代码——当然可以使用 alert()
,但这非常繁琐。在实际应用中可以轻松的关闭输出调试信息功能, Frost 服务器端会删除所有调试相关代码。
如果你看一下网页的代码,可以发现 Frost 被作为外部脚本文件引入:
<script type="text/javascript" src="frost/frost.php?debug=1"></script>
其src
属性指向 PHP 脚本,frost.php
,传入参数为 debug=1
——这将启动调试输出。在服务器端 PHP 脚本使用 JavaScript 文件作为输入,并删除所有浏览器不支持的代码。如果你想看看服务器上的 JavaScript 代码,请访问 http://frostlib.org/demo/frost/frost.js ——这是完整的 JavaScript 源代码。
除了提供尽量多浏览器可以使用的功能外,Frost 的另一个目标就是保持小的体积以减少载入时间。为完成上面的例子,下载的 Frost 代码有0.7kB——这是因为 Frost 还提供了许多其他功能。完整的 Frost 代码有 1.9kB...对于 JavaScript 库来说已经很小了。
使用 Frost 的好处如果我自己也能实现 Ajax ,为什么还要使用 Frost 库呢?下面是一些很好的原因:
你不想重复编写代码 ——上面的例子中这不是多大问题,但如果你需要更多功能并且实现不知道客户端浏览器呢? 你想减少与目标浏览器无关的代码 —— 如你想检查 XHR 对象或 ActiveX 是否存在,并返回合适的内容 你需要调试功能 —— 你很想知道程序运行中到底发生了什么,并且你觉着无休止的alert()
很烦人且浪费时间 你想处理离线情况 —— 你知道载入页面后,然后离线,然后点击链接会发生什么么?这取决于浏览器和设备。最佳的情况下连接将自动被复原,但大部分情况下都并非此结果。常见的结果是将永远停在检测 xhr.onreadystatechange
状态的语句,因为状态永远不会改变。这太糟糕了,因为已经在 getData()
中返回了 true
,结果导致链接无法显示——这意味着用户不会得到任何结果。Frost 处理回调函数的方式不同,因此可以为XHR请求设置超时,如果一段时间后什么也没有发生,请求会超时 Frost 将执行你设置的任何 JavaScript 函数,如通知用户请求失败并返回上一个页面。 你希望显示程序正在运行中 —— 通常情况下后台运行 Ajax 时都会显示等待动画,这样用户知道程序正在执行中。Frost 可在 XHR 请求时通过动画显示预定义图像;Frost 也在开发基于文字的动画。 目前 Frost 核心库大小为1.9kB,提供除调试外所有上述优点。如在开发阶段启用调试,则 Frost 大小为3.2kB。
为什么 Frost 仍未发布?如上所示,Frost 尝试输出最小的 JavaScript 文件——只输出目标浏览器能运行的 JavaScript 脚本,因此需要浏览器探测和浏览器能力数据库。这就是为什么还没有发布 Frost 的原因——开发者还在开发浏览器能力测试。Frost 打算与 WURFL[10] 和 DDWG[11]共享关于浏览器能力的数据。社区开发者将会尽快解决此问题。今年年底应该就能发布 working release。现在请使用 pre-release 版本!你可以加入 WURFL.[12] 中关于 Ajax 的邮件列表。
小节随着手机能力越来越强大,Mobile Ajax 会变得越来越重要。无论是移动设备平台还是桌面电脑平台,有相同 Ajax 最佳使用实践——应将 Ajax 视为某种增强,但不要强迫用户依赖 Ajax ——用户无法使用 Ajax 时也应能访问网页。在移动互联网开发中内容自适应是常见技术,为什么在 Mobile Ajax 中不使用呢?
如果你让我预测一下未来,我认为随着浏览器变得越来越强大以及限制 Ajax 的技术问题被一个个解决,Mobile Ajax 将以很多种方式演变。以后会有各种方式访问设备 API,如通过 JavaScript 对象访问 GPS 或其他应用程序。Mobile widget 和离线处理将变得更加流行。Ajax 将会其他技术配合使用( 如 SVG ,想象一下动态 SVG 图形!) 。
想进一步了解 Mobile Ajax 可以查看 Mobile Ajax FAQ [13],尽管此文章很久没有更新。PavingWays 的博客上[14] 我也写了一些关于 Mobile Ajax 的文章。dev.mobi[15] 中也有一些关于 Mobile Ajax 的文章。dev.opera.com[16] 上 Chris Mills 的文章也讨论了Opera Mini 中的 Ajax 问题。
参考文献[1] W3C One Web presentation
[2] Ajax on IE Mobile in 2005
[3] Ajit Jaokar on Mobile Ajax
[4] Mobile Ajax Workshop 2007
[5] Open Ajax Alliance Mobile Ajax Taskforce
[6] Mojax, Java based
[7] Opera Platform
[8] WAP 2.0 definition
[9] "Bulletproof Ajax" by Jeremy Keith
[10] WURFL project
[11] DDWG at W3C
[12] Ajax in WURFL (Yahoo! Group)
[13] Mobile Ajax FAQ
[14] Mobile Ajax Intro at PavingWays
[15] Mobile Ajax Intro at dev.mobi
[16] Chris Mills on Opera Mini 和 Ajax
[17] Official Frost Page
本文采用的授权是创作共用的“署名-非商业性使用-相同方式共享 2.5 通用许可”。
?
本文转自 http://kb.operachina.com/node/202