2014年12月

HTML5学习 之 XMLhttpRequset level1 和 level2的那些事

XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信。
最早,微软在IE 5引进了这个接口。因为它太有用,其他浏览器也模仿部署了,ajax操作因此得以诞生。
但是,这个接口一直没有标准化,每家浏览器的实现或多或少有点不同。HTML 5的概念形成后,W3C开始考虑标准化这个接口。2008年2月,就提出了XMLHttpRequest Level 2 草案。

一、XMLHttpRequest对象

 //新建XMLHttpRequest的实例
  var xhr = new XMLHttpRequest();
    //发出HTTP请求。
  xhr.open('GET', 'api.json');
  xhr.send();
//监控XMLHttpRequest对象的状态变化,指定回调函数。
  xhr.onreadystatechange = function(){
    if ( xhr.readyState == 4 && xhr.status == 200 ) {
      alert( xhr.responseText );
    } else {
      alert( xhr.statusText );
    }
  };

上面的代码包含了XMLHttpRequest level1 对象的主要属性:

  • xhr.readyState:XMLHttpRequest对象的状态,等于4表示数据已经接收完毕。
  • xhr.status:服务器返回的状态码,等于200表示一切正常。
  • xhr.responseText:服务器返回的文本数据
  • xhr.responseXML:服务器返回的XML格式的数据
  • xhr.statusText:服务器返回的状态文本。

二、XMLHttpRequest level1 的缺点

  • 只支持文本数据的传送,无法用来读取和上传二进制文件。
  • 传送和接收数据时,没有进度信息,只能提示有没有完成。
  • 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。

三、XMLHttpRequest level2的功能

XMLHttpRequest level2对象,针对XMLHttpRequest level1的缺点,做出了大幅改进。

1. 可以设置HTTP请求的时限。
增加了timeout属性,可以设置HTTP请求的时限。
  

xhr.timeout = 3000;
    //将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。
    //ontimeout事件,用来指定回调函数。
  xhr.ontimeout = function(event){
    alert('请求超时!');
  }

2. 可以使用FormData对象管理表单数据。

//新建一个FormData对象。
  var formData = new FormData();
//append 添加表单项。
  formData.append('username', '张三');
  formData.append('id', 123456);
  xhr.send(formData);

3. 可以上传文件。

//假定files是一个"选择文件"的表单元素(input[type="file"]),我们将它装入FormData对象。
  var formData = new FormData();
  for (var i = 0; i < files.length;i++) {
    formData.append('files[]', files[i]);
  }
  xhr.send(formData);

4. 可以请求不同域名下的数据(跨域请求)。

服务器端进行header设置。
见我的另外一博客 [CORS-AJAX POST跨域解决方案][1]

5. 可以获得数据传输的进度信息。

XMLHttpRequest Level2对象,传送数据的时候,有一个progress事件,用来返回进度信息。

它分成上传和下载两种情况。下载的progress事件属于XMLHttpRequest对象,上传的progress事件属于XMLHttpRequest.upload对象。
我们先定义progress事件的回调函数。

xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;

然后,在回调函数里面,使用这个事件的一些属性。

function updateProgress(event) {
    if (event.lengthComputable) {
      var percentComplete = event.loaded / event.total;
    }
  }

上面的代码中,event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0。

与progress事件相关的,还有其他五个事件,可以分别指定回调函数:

  1. load事件:传输成功完成。
  2. abort事件:传输被用户取消。
  3. error事件:传输中出现错误。
  4. loadstart事件:传输开始。
  5. loadEnd事件:传输结束,但是不知道成功还是失败。

HTML5学习之Communication API

Communication,顾名思义,是交流,是通信。在HTML5的页面,框架之间通信中,Communication API扮演着非常重要的作用。

既然是交流,必然有发送和接收2个过程。

在Communication API中,可以使用postMessage方法进行发送数据。接收的话只要监听一个名为messge的事件就可以了。

下面是一个例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>html5 页面发送信息测试</title>
    <script>
        function load(){
            var postBtn=document.getElementById("postMessage");
            postBtn.addEventListener("click",post,true);
        }
        function post(){
            var frame=document.getElementById("frame").contentWindow;
            frame.postMessage("hello world","*");
        }
    </script>
</head>
<body onload="load()">
<h2>html5 页面发送信息测试</h2>
<iframe id="frame" src="communication2.html"></iframe>

<button id="postMessage">发送信息</button>
</body>
</html>

在上述代码中,我们向id为frame的iframe发送了消息,那么communication2.html是如何接收呢?
上代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>html5 页面发送信息测试-接收端</title>
    <script>
        function load(){
            window.addEventListener("message",getMessage,true);
        }
        function getMessage(e){
            var message=document.getElementById("messageText");
            message.innerHTML="源:"+e.origin+"<br/>内容:"+e.data;
        }
    </script>
</head>
<body onload="load()">
<h2>html5 页面发送信息测试-接收端</h2>
<p id="messageText"></p>
</body>
</html>

使用addEventListener监听message事件,当有消息,就会执行getMessage回调。

就是这么简单!

HTML5学习之Geolocation

以前如果要获取互联网用户所在地都是根据用户的IP地址来获取地理位置,这样获取到的数据和真实数据有很大的偏差。为了获取更加精确的位置,可以使用了html5的geolocation来获取经纬度,然后再获取所在地理位置,如何获取,我在下面会说到。先说下基本概念。

  Geolocation在的navigator 对象中,我们可以通过 navigator.geolocation 来使用它。不支持 geolocation 的浏览器并不包含这一对象,那么可以通过下面的代码来做能力检测,对不同的浏览器做不同的处理。在访问 geolocation 对象时,即调用 geolocation 下面的方法时,浏览器会弹出提示,询问用户是否许可网站提供的位置服务,只有在得到用户许可过后,服务才会继续,否则将被停止。 

  常用的navigator.geolocation对象有以下三种方法:

  1. 获取当前地理位置:navigator.geolocation.getCurrentPosition(success_callback_function,
    error_callback_function, position_options)
  2. 持续获取地理位置:navigator.geolocation.watchPosition(success_callback_function,
    error_callback_function, position_options)
  3. 清除持续获取地理位置事件:navigator.geolocation.clearWatch(watch_position_id)

  参数position_options是配置项,由JSON格式传入:

  enableHighAccuracy:true/false,它将告诉浏览器是否启用高精度设备,所谓的高精度设备包含但不局限于前面所提到的 GPS 和 WIFI,值为 true 的时候,浏览器会尝试启用这些设备,默认指为 true,在这种情况下,浏览器会尽可能地进行更为精确的查询,简单地说,如果用户有可用的 GPS 设备,会返回 GPS 设备的查询结果,IP 是最后的选择,对于移动设备来说,网络接入点(基站)或许成为另一个选择,对此我还没有完全了解,但根据测试,即时没有任何额外功能的手机,也能够得到更为精确的查询结果。

  maximumAge:单位毫秒,告诉设备缓存时间,主要用于设备的省电或者节省带宽方面。

  timeout:单位毫秒,超时事件,获取位置信息时超出设定的这个时长,将会触发错误,捕获错误的函数将被调用,并且错误码指向TIMEOUT。

var position_option = {
                enableHighAccuracy: true,
                maximumAge: 30000,
                timeout: 20000
            };
navigator.geolocation.getCurrentPosition(getPositionSuccess, getPositionError, position_option);
function getPositionSuccess( position ){
        var lat = position.coords.latitude;
        var lng = position.coords.longitude;
        alert( "您所在的位置: 纬度" + lat + ",经度" + lng );
        if(typeof position.address !== "undefined"){
                var country = position.address.country;
                var province = position.address.region;
                var city = position.address.city;
                alert(' 您位于 ' + country + province + '省' + city +'市');
        }
}
coords其他返回信息:

coords.accuracy:返回经纬度的精度(米)

coords.speed :速度

coords.altitude :当前的高度,海拔(米)

coords.altitudeAccuracy:高度的精度(米)

coords.heading:朝向

function getPositionError(error) {
    switch (error.code) {
        case error.TIMEOUT:
            alert("连接超时,请重试");
            break;
        case error.PERMISSION_DENIED:
            alert("您拒绝了使用位置共享服务,查询已取消");
            break;
        case error.POSITION_UNAVAILABLE:
            alert("获取位置信息失败");
            break;
    }
}

在获取城市信息的时候只有firefox会提供城市地址。chrom不会给出。当然sogou地图提供了获取位置信息的api。

链接地址:http://map.sogou.com/api/documentation/javascript/api2.5/interface_regeocode.html  

移动设备持续获取地理位置方法:navigator.geolocation.watchPosition

对于使用移动设备的用户来说,位置并不是固定的,W3C 当然也考虑到了这一点,watchPosition 是一个专门用来处理这一情况的方法,watchPosition 被调用后,浏览器会跟踪设备的位置,每一次位置的变化,watchPosition 中的代码都将会被执行。对于致力于移动设备 web 开发的同学来说,这个方法是及其重要的,它也许将会改变 web 移动客户端的格局。
使用navigator.geolocation.clearWatch既可以清除navigator.geolocation.watchPosition的监控事件。