基础铺垫
Javascript XMLHttpRequest网络请求
> XMLHttpRequest 是一个 JavaScript 对象,它最初由微软设计,随后被 Mozilla、Apple 和 Google采纳. 如今,该对象已经被 W3C组织标准化. 通过它,你可以很容易的取回一个URL上的资源数据. 尽管名字里有XML, 但 XMLHttpRequest 可以取回所有类型的数据资源,并不局限于XML。 而且除了HTTP ,它还支持file 和 ftp 协议. —— MDN XMLHttpRequest
XMLHttpRequest
让发送一个HTTP
请求变得非常容易。你只需要简单的创建一个请求对象实例,打开一个URL
,然后发送这个请求。当传输完毕后,结果的HTTP
状态以及返回的响应内容也可以从请求对象中获取。
XMLHttpRequest网络请求的一般步骤:
第一步:创建一个 XMLHttpRequest 实例
new XMLHttpRequest();
第二步:初始化HTTP请求参数
void open(
DOMString method,
DOMString url,
optional boolean async,
optional DOMString user,
optional DOMString password
);
- method:请求所使用的
HTTP
方法; 例如"GET"
,"POST"
,"PUT"
,"DELETE"
等. 如果下个参数是非HTTP(S)
的URL
,则忽略该参数. - url:该请求所要访问的
URL
- async:一个可选的布尔值参数,默认为
true
,意味着是否执行异步操作,如果值为false
,则send()
方法不会返回任何东西,直到接受到了服务器的返回数据。如果为值为true
,一个对开发者透明的通知会发送到相关的事件监听者。这个值必须是true
,如果multipart
属性是true
,否则将会出现一个意外。 - user:用户名,可选参数,为授权使用;默认参数为空
string
. - password:密码,可选参数,为授权使用;默认参数为空
string
.
第三步:发送请求
send();
发送请求. 如果该请求是异步模式(默认),该方法会立刻返回. 相反,如果请求是同步模式,则直到请求的响应完全接受以后,该方法才会返回.
如下例:
var xhr = new XMLHttpRequest();
xhr.onload = function () {
console.log(this.responseText);
};
xhr.onreadystatechange = function() {
console.log(this.readyState);
};
xhr.open("get", "https://www.baidu.com", true);
xhr.send();
我们在hbuilder里面打开,控制台会报错:
[Web浏览器] "XMLHttpRequest cannot load https://www.baidu.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8020' is therefore not allowed access."
用浏览器打开,按F12
在控制台console
下查看也会发现上述错误,这是为啥呢?
这是因为普通网页能够使用XMLHttpRequest
对象发送或者接受服务器数据, 但是它们受限于同源策略。只要先获取了跨域请求许可,就可以进行跨域请求。
> 同源策略:如果两个页面的协议、域名和端口是完全相同的,那么它们就是同源的。同源策略是为了防止从一个地址加载的文档或脚本访问或者设置从另外一个地址加载的文档的属性。如果两个页面的主域名相同,则还可以通过设置document.domain
属性将它们认为是同源的。
跨域请求的几种常用方法:
第一种:CORS,使用XMLHttpRequest对象
CORS 的全称是 Cross-Origin Resource Sharing,即跨域资源共享。他的原理就是使用自定义的 HTTP 头部,让服务器与浏览器进行沟通,主要是通过设置响应头的 Access-Control-Allow-Origin 来达到目的的。这样,XMLHttpRequest 就能跨域了。
在服务器端添加响应头Access-Control-Allow-Origin
,使用XMLHttpRequest
对象请求。值得注意的是,正常情况下的 XMLHttpRequest 是只发送一次请求的,但是跨域问题下很可能是会发送两次的请求(预发送)。
PHP:
header('Access-Control-Allow-Origin: *');
java:
response.addHeader( "Access-Control-Allow-Origin", "*" );
第二种:Jsonp,只适用于get请求
Jsonp
的跨域不是用XMLHttpRequest
实现的,而是一个script
标签,script
是可以跨域的,回调函数作为get
参数传入请求里。
原理很简单,比如你在A域名请求B域名:
- 在A域名的页面中使用script标签src写成B域名中服务器的URL
script标签是可以跨域的,比如你调用Google Map或Google Analytics时引入的js就是google域名下的。
- 后端程序在最后需要把一段js代码的字符串print出来,这样就可以运行A域名js中写好的callback方法,将要返回的数据放入参数就可以了
A域名中的js文件:
<script type="text/javascript" src="http://www.b.com/action?callback=myCallback"></script>
<script type="text/javascript">
function myCallback (data) {
alert(data);
}
</script>
B域名中服务器
String cb = get('callback');
Int b = '我是数据';
print('<script type="text/javascript"> ' + cb + '(' + b + '); </script>');
后端print数据到页面中后就会这样
<script type="text/javascript">
myCallback('我是数据');
</script>
> 注:引用自segmentfault 的tychio的回答。
总之,不论是XMLHttpRequest
的跨域,还是Jsonp
,都是需要请求的网站服务器端提供支持,在愿意分享给你数据的情况下你才能得到。在对方没有提供支持的情况下,你是取不到它的数据的。当然跨域的解决方案有很多种,由于本人没有实践过,没有实践就没有发言权,这里给大家贴一个帖子,自己跨域自行验证,浅谈浏览器端JavaScript跨域解决方法。
html5+ XMLHttpRequest网络请求
上面我们花了很大篇幅讲解了JavaScript XMLHttpRequest
对象,而且也简单的讲解了同源策略和跨域请求的常用方法,我们注意到无论是JavaScript XMLHttpRequest
还是jsonp
都需要通过服务器端的支持才能实现跨域,另外还有几种也有一定的局限性,所以总还是让人觉得美中不足。html5+
提供了一个XMLHttpRequest
模块,在APP
端很完美的解决了这种问题,而且提供了和JavaScript XMLHttpRequest
对象用法类似的一系列属性方法。由于本文的重在在于讲解html5+ XMLHttpRequest
,所以前面的JavaScript XMLHttpRequest
相关的属性方法只是初略介绍了一下,下面重点介绍html5+ XMLHttpRequest
模块。
适用范围:
由于html5+ XMLHttpRequest
是一种拓展方案,所以需要底层支持,基于html5+ XMLHttpRequest
的方法不能用于非5+
环境,如果对这些概念不清楚的欢迎先阅读我之前写的文章mui初级入门教程(一)— 菜鸟入手mui的学习路线。
我们用hbuilder
新建一个app工程,然后运行下面的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
</head>
<body>
<script type="text/javascript">
document.addEventListener('plusready', function(){
var xhr = new plus.net.XMLHttpRequest();
xhr.onreadystatechange = function () {
switch ( xhr.readyState ) {
case 0:
console.log( "xhr请求已初始化" );
break;
case 1:
console.log( "xhr请求已打开" );
break;
case 2:
console.log( "xhr请求已发送" );
break;
case 3:
console.log( "xhr请求已响应");
break;
case 4:
if ( xhr.status == 200 ) {
alert( "xhr请求成功:"+xhr.responseText );
} else {
console.log( "xhr请求失败:"+xhr.readyState );
}
break;
default :
break;
}
}
xhr.open("GET", "https://www.baidu.com/");
xhr.send();
}, false );
</script>
</body>
</html>
我们会发现最后弹出了弹框,里面写有百度首页的代码。
XMLHttpRequest对象:
创建一个XMLHttpRequest
对象,对象创建时不触发任何时间和网络请求,需和open
,send
方法配合使用。
var xhr = new plus.net.XMLHttpRequest();
xhr.open(method, url);
xhr.send();
> XMLHttpRequest的属性:
- **readyState: **HTTP 请求的状态
- response: 请求从服务器接收到的响应数据
- responseText: 请求从服务器接收到的响应数据(字符串数据)
- responseType:请求响应数据response的类型
- responseXML: 请求响应的Document对象
- status: 服务器返回的HTTP状态代码
- statusText: 服务器返回的HTTP状态描述
- timeout: 请求服务器的超时时间,单位为毫秒(ms)
- withCredentials: 是否支持跨域请求
> XMLHttpRequest的方法:
- **abort: **取消当前响应,关闭连接并且结束任何未决的网络活动
- **getAllResponseHeaders: **获取HTTP响应头部信息
- **getResponseHeader: **获取指定的HTTP响应头部的值
- **open: **初始化HTTP请求参数,例如URL和HTTP方法,但是并不发送请求
- send: 发送HTTP请求
- setRequestHeader: 指定一个HTTP请求的Header
> XMLHttpRequest的事件:
- onreadystatechange: 网络请求状态发生变化事件
- onloadstart: 网络请求开始事件
- onprogress: 网络请求传输数据事件
- onabort: 网络请求取消事件
- onerror: 网络请求错误事件
- onload: 网络请求成功事件
- ontimeout: 网络请求超时事件
- onloadend: 网络请求结束事件