关于Mobile Ajax 和 Frost Ajax 库

Mobile Ajax 和 Frost Ajax 库

作者 Rocco Georgi · 2007年12月5日

本文翻译自 Mobile Ajax And The Frost Ajax Library

简述

本文介绍了如何为移动设备创建使用 Ajax 的网站。下面将讨论移动 Ajax 和桌面 Ajax 的不同、移动 Ajax 有哪些特别的问题和限制及解决方法。一个解决方法就是使用 Frost Ajax 库,这是一个帮助在移动设备上开发基于 Ajax 服务的库。本文将给出使用 Frost 具体实例。本文适合想创建不仅限于桌面设备的跨设备 Ajax 网站的开发者。

必备知识

如果你了解 HTML、JavaScript 和 XMLHttpRequest 对象,你将很容易理解此文章。了解 DOM 脚本、CSS 和 Ajax 库 (如 prototype, jQuery, dojo, YUI 等)也会有所帮助,但这不是必须的。

一些基本概念和定义

Mobile Ajax 现在是很时髦的概念。一方面我很高兴有了一个词语能概括下文要讨论的问题,另一方面确发现很难确切定义什么是 Mobile Ajax。也许需要某人为此建立维基百科页面了...

我不想为任何事物下定义,每个人都有其各自的定义。下面的定义仅是为了后文描述方便:

  • Mobile Web: 目前正在激烈讨论究竟什么是移动互联网。我个人认可 "One Web" [1]的定义,One Web 可以有不同部分,其中一部分目标是手机和其他手持设备。这就是我眼中的 Mobile Web ,其包含多种不同标准 (如 XHTML-MP) 和各种不同的Web浏览器。移动设备浏览器受性能和带宽限制,无法支持全部网络标准。所以这里我区别移动设备和桌面电脑环境。
  • 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,移动设备浏览器需要支持以下特性:

  1. 异步发送/接收数据 (通过 XMLHttpRequest 对象或者 ActiveX)
  2. 数据到达后可以理解执行某些操作 (通常通过回调函数)
  3. 在客户端显示收到的数据

第三点需要 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() 返回 truefalse,决定是否执行链接。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 实现上面的例子

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 和用于显示数据的容器的 idf() 返回 truefalse,如果发生错误,浏览器可以显示链接 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

相关推荐