使用动态的script标签发起Web Services请求

使用动态的script标签和特殊的与JSON相关的JavaScript类来轻松实现无XML的Web services。

从Ajax应用发起到第三方Web服务的请求是一种痛苦,但是新的Web服务减轻了这种痛苦,它提供了返回JSON格式[Hack #7]结果的选择以代替XML格式。事实上,如果你使用动态script标签方法发起Web服务请求,而且Web服务可让你指定一个JavaScript回调函数,你就可以以一种无缝的跨域跨浏览器的方式自由访问Web服务。

下面是你尝试这个动态的script标签请求所需要的:

l   我的JSONscriptRequest类

l   访问返回JSON格式结果并可让你指定回调函数的Web service

为创建JSONscriptRequest类,我提炼了大量已有的 信息,然后调整其以满足上面的第二个要求。直到最近,要找到满足那个要求的Web service近乎不可能,除非你自己写一个。幸运的是,Yahoo!已经开始在它的许多Web service上提供其他的选择。特别地,Yahoo!的与很多搜索相关的Web service,以及它的geocoding、map image和traffic等Web service,现在可以返回封装在一个回调函数里的JSON值。

使用Geocoding Web Service

比起使用XMLHttpRequest对象和代理,这个东西算很容 易的。JSONscript- Request类做了创建script标签的脏活;这个标签动态地发起实际的Web service请求。举个快速的例子,这里我将使用Yahoo!的Geocoding Web service,将一个邮编94107转化成一个经/纬对:

<html>

<body>

//包含JSONscriptRequest类

<script type="text/javascript" src="jsr_class.js"></script>

<script type="text/javascript">

//定义回调函数

function getGeo(jsonData) {    

    alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude +

          ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);

    bObj.removeScriptTag();

}

// web service 调用

var req = 'http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo

          &output=json&callback=getGeo&location=94107';

//创建一个新的Request对象

bObj = new JSONscriptRequest(req);

//构建动态脚本标签

bObj.buildScriptTag();

//添加脚本标签到页面中

bObj.addScriptTag();

</script>

</body>

</html>

运行这个程序发起一个到Yahoo!的Geocoing Web service的请求,会弹出如图9-5所示的alert框。这个alert框显示了邮编94107的经度和纬度。

图9-5:从Yahoo的Geocoding Web service所得的坐标

Web service请示(上述script里的req变量)指出Web service应该返回JSON编码的数据(output=json),而且数据应该被封装在一个名为getGeo()(callback= getGeo)的回调函数里。你可以剪切并粘贴代码中的URL到你的浏览器中,然后就会看到Web service的输出。输出如下:

getGeo({"ResultSet":{"Result":[{"precision":"zip","Latitude":"37.7668"

,"Longitude":"-122.3959","Address":"","City":"SAN

FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});

这是一个有效的 JavaScript语句,所以它可以是返回JavaScript的script标签的target(没有回调函数的原始JSON数据,不是有效的 JavaScript语句,所以如果它作为script标签的target,那么就会载入失败)。作为比较,看一下这个调用的XML版本的输出(为这本书 格式化过):

<?xml version="1.0" encoding="UTF-8"?>

<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns=

"urn:yahoo:maps" xsi:schemaLocation=

"urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.

xsd">

<Result precision="zip"><Latitude>37.7668</Latitude>

<Longitude>-122.3959</Longitude><Address></Address>

<City>SAN FRANCISCO</City><State>CA</State><Zip>94107</Zip>

<Country>US</Country></Result>

</ResultSet>

JSONscriptRequest对象的buildScriptTag方法建立了如下的script标签:

<script src="getGeo({"ResultSet":{"Result":[{"precision":"zip",

"Latitude":"37.7668","Longitude":"-122.3959","Address":"","City":"SAN

FRANCISCO","State":"CA","Zip":"94107","Country":"US"}]}});"

 type="text/javascript">

要实际执行Web service请求,script标签就要加到页面里去。addScriptTag方法将script标签附加到已经载入到你的浏览器窗口中的HTML页 面里。这个动作引起了getGeo()函数的调用,同时JSON编码的数据被传送给这个函数。下面看看这个标签中最神奇的部分;它是使用JSON编码的数 据而不是XML的副作用。当JSON编码的数据以字符串形式作为JavaScript函数的参数时,JavaScript解释器自动将JSON返回值转化 成一个JavaScript对象。基本上,解析的步骤是自动完成的,你可以立即引用这些数据:

alert('Latitude = ' + jsonData.ResultSet.Result[0].Latitude +

       ' Longitude = ' + jsonData.ResultSet.Result[0].Longitude);

正反面

HTML script标签是自由访问基于浏览器的应用的最后边界。从你的角度看来,它可能是一个安全漏洞,或者是一个使富客户端更丰富的工具。然而,它最普遍的用处就是网络广告商使用它将多姿多彩的广告拉到你的网页中。

对于普通的Ajax或者Ajaj(Asynchronous JavaScript and JSON)开发者而言,动态script标签方法在某些场景下能使事情变得简单。然而,XMLHttpRequest对象仍然是更可靠的、灵活安全的请求机制(见表9-1)。

表9-1  XMLHttpRequest 与动态script标签对照表

XmlHttpRequest

Dynamic script tag

跨浏览器兼容性

No

Yes

强制的跨域浏览器安全

Yes

No

是否能接收HTTP状态码

Yes

No (fails on any HTTP status other than 200)

是否支持HTTP GET和POST

Yes

No (GET only)

能否发送/接收HTTP头

Yes

No

能否接收XML

Yes

Yes (but only embedded in a JavaScript statement)

能否接收JSON

Yes

Yes (but only embedded in a JavaScript statement)

是否提供同步和异步调用

Yes

No (asynchronous only)

script标签的主要优点在于它并不受Web浏览器跨域安全限制的束缚,以及比

XMLHttpRequest具备更好的浏览器兼容性。进一步来说,如果你的Web service碰巧提供了JSON输出以及一个回调函数,你可以从JavaScript应用中敏捷地访问Web service,而无需解析返回的数据。

在所有的最新浏览器中 XMLHttpRequest都有效,但是IE的实现和其他主要浏览器稍微有所不同,从而需要一个兼容性层(例如Sarissa)来使其工作在所有浏览器 上。XMLHttpRequest能接收原始的JSON数据,还可以接收XML、普通文本以及HTML。事实上,它能轻松地处理任何非二进制数据。它还能 发送和接收独立的HTTP头部,可以执行HTTP GET和POST请求,同时支持同步和异步调用。一言以蔽之,如果你的Web service请求存在问题,譬如无效的XML或者一个服务器错误,XMLHttpRequest为程序员提供了解决这种情况的工具。

相比较而言,script标签 提供很少的XMLHttpRequest能力。最值得注意的坏处是它不能优雅地处理错误。如果Web service返回无效的JavaScript语句给script标签,就会产生一个JavaScript错误。如果Web service返回封装在一个回调函数里的无效JSON数据,那么当无效的JSON数据被传给回调函数时会返回一个JavaScript错误。而且,如果 你的Web service返回除200(成功)外的HTTP返回码,script标签会默默的失败。

事实上,script标签请求 并不是在所有的浏览器上都以同一方式工作。事件处理机制(你如何等待标签来载入)有些不同。技术上来说,动态生成的script标签会异步载入,但是没有 可靠的、跨平台的方式来等待script标签载入。微软的IE使用了这里描述的一个方法,而HTML4.0规范建议采用onload事件处理器(尽管它并 不是在所有的浏览器上都可用)。

围绕script标签的安全问 题也不能被忽视。下载到你的浏览器中的恶意脚本以与你页面中的其他脚本一样的权限级别运行。因此,恶意的脚本能够偷取你的cookies,或者滥用你在服 务器端拥有的授权级别。这些恶意脚本能更轻易地使用script标签发送和接收偷来的数据。出于此原因,使用动态script标签方法的应用应该仔细检 查。

有了这些缺点,程序员就不会一窝蜂地使用script标签来实现或重新实现Web service请求。然而它对于脚本应用来说仍然是一门有用的技术——可以轻易地从第三方检索非机密数据。

参考资料

JSONscriptRequest类:http://www.xml.com/2005/12/21/examples/jsr_class.zip;Yahoo! Web Services;Geocoding API:http://developer.yahoo.net/maps/rest/V1/ geocode.html

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值