英文原文:HTML5 fundamentals, Part 3: The power of HTML5 APIs
那么,什么是API呢?
应用编程接口(application program interface,API)是访问一个软件应用的编程指令和标准的集合。通过使用API,你就可以设计出由API提供的服务来驱动的产品。
HTML5拥有一些新的API,例如:
1. 一个与新的画布元素一起使用的2D绘图API,用于渲染图形或是其他的视觉图像。
2. 一个支持离线web应用的缓存机制的API。
3. 一个播放视频和音频的API,与新的视频和音频元素一起使用。
4. 一个历史记录API,其把浏览历史变成可访问的,并允许把页面添加到这一历史中。
5. 一个和draggable属性一起使用的拖放API。
6. 一个和contenteditable属性一起使用的编辑API。
7. 键-值对以及内嵌的SQL数据库的客户端存储,使用了JavaScript API。
本篇文章重点关注两个API:Geolocation和Web Worker,首先对这些API本身进行分析,然后创建一个包含这两个API的页面。
无处不在的业务:Geolocation
Geolocation API被用来确定和分享地理位置,API返回经度和纬度坐标——这是企业可用来在这一坐标附近的区域提供服务的信息,这类服务通常被称作基于位置的服务(location-based service, LBS)。
LBS以地理数据源为参考,这些地理数据源被用来标识被监控仪器的物理位置,从而识别出与这一位置相关的人。这一功能赋予感兴趣的各方与这一个人进行交互的机会,这种交互是基于一些以地理位置为中心的兴趣点市场来进行的。
商业实际上是为客户创造品质、实用性和价值,并同时为利益相关者、债权人、股东、员工和供应商创造经济和金融利益。以地理位置为驱动力的LBS使得跟踪和监控一个包裹(或者使用了非浏览器设备或浏览器的个人)变得相当容易。从商业化的角度来说,地理位置所涉及的就是使用地理资产来确定某人或是某物所处的位置,然后把这一特定的一组信息出售给想要把这些信息用于社会、商业或是其他目的的的任何人,只要信息的拥有者的这种做法是法律许可的就可以了。
地理定位(geolocation)的工作方式
Geolocation API基于navigator这一全局对象的一个新属性:navigator.geolocation,这一JavaScript的navigator对象提供了一些关于访问者的浏览器和系统的有用信息。Geolocation可以确定使用了IP地址、基于web的数据库、无线网络连接,以及三角定位或是GPS技术的访问者的经度和纬度。应该要注意的一点是,由Geolocation提供的信息的准确性会基于获取信息的手段而发生变化。偶然情况下,在一些位置上,你有可能不能获得明确的地理位置读数或是一点数据都接收不到。
脚本可使用navigator.geolocation对象来确定与用户的宿主设备相关的位置信息,在检索到位置信息之后,一个位置对象就会被创建出来,并使用这些数据做填充。
navigator.geolocation对象有三个方法:
1. getCurrentPosition()
2. watchPosition()
3. clearWatch()
getCurrentPosition()方法
getCurrentPosition()方法检索用户的当前位置,但只检索一次。当该方法被脚本调用时,方法以异步的方式来尝试获取宿主设备的当前位置。异步通信意味着发送者和接收者并未同时地加入到这一通信过程中,使用异步通信能让浏览器继续进行其他方面的活动,这样它就无需等待来自接收实体的响应。
getCurrentPosition()方法最多可以有三个参数:
1. geolocationSuccess:带回当前位置的回调(callback)(必需的)
2. geolocationError. 有错误发生时使用的回调(可选的)
3. geolocationOptions. 地理位置选项(可选的)
navigator.geolocation.getCurrentPositon()方法使用一个Position对象作为参数来把宿主设备的当前位置返回给geolocationSuccess这一回调,如果有错误发生的话,geolocationError回调会使用一个PositionError对象来做调用。你可以设置geolocationOptions的三个属性:enableHighAccuracy、timeout和maximumAge,这些可选属性相应的作用分别是启用了高的精确性,如果设备支持这种高精确性的话;一个超时时段,这是位置应该被返回的最长等待时间;以及一个最大的时间数,缓存的位置在这一时间段内可被使用。
getCurrentPosition()方法的调用如下所示:
void navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationError, geolocationOptions);
watchPosition()方法
watchPosition()方法定期轮询用户的位置,查看用户的位置是否发生改变。其最多可带三个参数。
当watchPosition被调用时,其异步地启动一个查看过程,这一过程涉及了一个新的Position对象的获取和一个watchID的创建。如果这一获取操作是成功的,则相关的使用一个Position对象作为参数的geolocationSuccess就会被调用。在失败时涉及的操作则是使用一个非空的geolocationError参数来调用该方法,watchPosition方法使用一个PositionError对象作为参数来生成geolocationError。当设备的位置发生改变时,一个合适的带有新的Position对象的回调就会被调用。
watchPosition()方法的调用如下所示:
long navigator.geolocation.watchPosition(geolocationSuccess, geolocationError, geolocationOptions);
clearWatch()方法
clearWatch()方法终止正在进行的watchPosition(),该方法只能带一个参数。在调用时,其找到之前已经开始了的watchID参数并立即停止它。
clearWatch()方法的调用如下所示:
void navigator.geolocation.clearWatch(watchID)
Geolocation数据:Position对象
Geolocation API返回一个地理上的Position对象,该对象有两个属性:timestamp和coords。timestamp属性表示地理位置数据的创建时间,coords属性又包含七个属性:
1. coords.latitude:估计纬度
2. coords.longitude:估计经度
3. coords.altitude:估计高度
4. coords.accuracy:所提供的以米为单位的经度和纬度估计的精确度
5. coords.altitudeAccuracy:所提供的以米为单位的高度估计的精确度
6. coords.heading: 宿主设备当前移动的角度方向,相对于正北方向顺时针计算
7. coords.speed:以米每秒为单位的设备的当前对地速度
这些属性中只有三项是保证有的:coords.latitude、coords.longitude和coords.accuracy,其余的返回null,这取决于设备的能力和其所采用的后端定位服务器。如果可能的话,heading和speed属性可以基于用户之前的位置计算出来。
发挥救援作用的web worker
web worker(web工作线程)补救了并发所引起的问题,web worker是HTML5家族对JavaScript单线程问题的回答:它们在与主页面分开的线程中运行处理过程,保留页面以用于主要的功能,比如说维持一个稳定的UI等。
一个web worker是一个在后台加载并执行的JavaScript文件,这些worker允许你动态地加载一个JavaScript,然后使用不会影响到UI的后台进程来执行脚本。web worker的访问是受限的,其只允许传递字符串。因为web worker不使用浏览器的UI线程,所以他们不允许访问DOM。Workers可以使用self和this引用访问worker的全局变量(Workers can use both self and this references for the worker's global scope),worker和父页面的通信是通过使用事件模型和postMessage()方法来实现的。
因为web worker有多线程行为,因此它们只能访问JavaScript功能的一个子集,web worker可以:
1. 访问navigator对象
2. 使用只读的位置对象
3. 执行XMLHttpRequest以发送HTTP或是HTTPS请求
4. 使用setTimeout()/clearTimeout()和setInterval()/clearInterval()来设置时间或是时间间隔
5. 访问应用的缓存
6. 使用 importScripts() 方法来导入外部的脚本
7. 产生其他的web worker(subworker必需有着与主页面一样的来源,且必须放置于与父worker同样的地点。)
web worker有两种类型:专用型的worker和共享型的worker。
专用型web worker
专用型worker与创建它的脚本连接在一起,它可以与其他的worker或是浏览器组件通信,但是他不能与DOM通信。
专用型worker的创建方法是把一个JavaScript文件名传递给一个新的worker实例,通过指定worker的执行脚本URI使用Worker()构造函数来创建一个新的worker。要创建一个专用型worker的话,输入下面给出的代码,这一代码创建了一个新的专用的Worker对象:
- var worker = new Worker('worker.js');
共享型web worker
共享型web worker和专用型worker一样,不能访问DOM,并且对窗体属性的访问也受到限制。共享型web worker只能与其他来自同一个域的共享型web worker通信,它的创建方法是把一个JavaScript名称传递给一个新的共享型worker的实例来创建。
页面脚本可以与共享型web worker通信,而然,与专用型web worker不同的是,通信是通过使用一个端口(port)对象并附加上一个消息事件处理程序来进行的。另外,在使用第一个postMessage()之前,你必须要调用端口的start()方法。
在收到web worker脚本的首个消息之后,共享型web worker把一个事件处理程序附加到激活的端口上。一般情况下,处理程序会运行自己的postMessage()方法来把一个消息返回给调用代码,接着端口的start()方法生成一个有效的消息进程。
为了创建一个共享型web worker,你必须要创建一个SharedWorker对象而不是一个Worker对象。下面的代码说明了如何创建一个新的SharedWorker对象:
- var worker = new SharedWorker('worker.js');
构造一个包含了这两个API的页面
你将设计一个包含了Geolocation和Web Worker API的基本工作模式的页面,此外,你还会用到Google Map API来渲染作为地图收集来的数据。
页面的组织如图1所示,其包含了一个使用< header></header>标签来创建的Header区,一个使用<section>< /section>标签来创建的Section区,以及一个使用<aside></aside>标签来创建的Aside区。
图1. API页面的布局
<section>和<aside>区包含了API,Section区包含了Geolocation API,Aside区包含了web worker,其用来计算素数。
在执行时,网页的显示如图2所示。如果要查看地理位置数据的话,你首先必须要同意共享你的信息。web worker在页面加载时启动,如果你想看一看找到的素数的话,点击Display Web Worker按钮。
图2. API网页
HTML文件
HTML文件一开始的内容是清单1所示的标准的HTML5信息,<head>部分包含了一个到Google Maps API的调用,把sensor的值设置为False。使用Google Maps API对你状态的要求是,你的应用是否在使用一个传感器,比如说GPS来确立位置。你必须为你的Google Maps API应用声明一个值为True或是False的sensor参数,sensor的值必须被声明。<head>标签还包含了到JavaScript和CSS3文件的链接,这些文件被用来处理网页的功能和格式。
清单1. HTML文件开始部分的内容
- <!doctype html>
- <html>
- <head>
- <title>Basic GeoLocation Map & Web Worker Prime Number Calculator< /title>
- <script src="http://maps.google.com/maps/api/js?sensor=false"
- type="text/javascript"></script>
- <LINK href="GeolocationWebWorker.css" rel="stylesheet" type="text/css">
- <script src="HTML-Part3-GeolocationWebWorker.js" type="text/javascript"></script>
- </head>
<body>标签包含了onLoad事件,该事件调用地理定位的初始化函数,如清单2所示。该函数检验地理定位是否可在这一浏览器中使用,这一初始化函数放在JavaScript文件中。如果浏览器可以和Geolocation API通信的话,地图就会被渲染。
清单2. 初始化Geolocation
- <body onLoad="initGeoApp();">
- <header>
- <hgroup>
- <h1>Geolocation & Web Worker</h1>
- <h2>Making it work</h2>
- </hgroup>
- </header>
清单3中给出的<section>标签包含了navigator.geolocation对象的输出显示信息,API返回的经度和纬度被用来创建地图画布,Position的coords数据也通过使用<span></span>标签显示出来。
清单3. Geolocation的地图和位置
- <section>
- <p>This is the geolocation example map.</p>
- <div id="map_canvas" ></div>
- <p>This is the output from the navigator.geolocation object.</p>
- <table>
- <tr>
- <td>accuracy:</td>
- <td>< span id="accuracyOutput"></span></td>
- </tr>
- <tr>
- <td>altitude:</td>
- <td><span id="altitudeOutput"></span></td>
- </tr>
- <tr>
- <td>altitudeAccuracy:</td>
- <td><span id="altitudeAccuracyOutput"></span></td>
- </tr>
- <tr>
- <td>heading:</td>
- <td><span id="headingOutput"></span></td>
- </tr>
- <tr>
- <td>latitude:</td>
- <td><span id="latitudeOutput"></span></td>
- </tr>
- <tr>
- <td>longitude:</td>
- <td><span id="longitudeOutput"></span></td>
- </tr>
- <tr>
- <td>speed:</td>
- <td><span id="speedOutput"></span></td>
- </tr>
- </table>
- </section>
- <aside>
- <p>This is the Web Worker. </p>
- <p>Prime number calculation result:
- <output id="result"></output></p>
Web Worker计算素数,<output>这一新的标签被用来显示web worker提供的计算结果,<output>标签中的ID与JavaScript用来标识其要执行的计算的ID是相同的。在<span>和<output>标签中用到的ID使得它们在DOM中是可访问的,没有引用ID的话,JavaScript就不知道要使用哪一个<span>和<output>。清单4给出了web worker的输出。
清单4. web worker的输出
- <aside>
- <p>This is the Web Worker. </p>
- <p>Prime number calculation result:
- <output id="result"></output></p>
<input>中用到的onClick首先显示由素数(Prime Number)web worker计算出来的值,而第二个onClick则是被用来停止web worker的。清单5给出了代码。在按钮被点击时,displayWorker()函数引发显示web worker计算出来的结果。web worker在页面载入后开始计算素数。