www.78ajax,ajax异步请求/同源策略/跨域传值

基本概念

Ajax 全称是异步的 JavaScript 和 XML 。 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个网页页面。

Ajax 具有以下优点和缺点:

优点

无需刷新页面,用户体验好;

异步与服务器通信,不影响主进程,响应更迅速;

可以把部分服务器的工作放在客户端的浏览器完成,减轻服务器压力,减少冗余请求和响应;

Ajax 是前端开发的标准化技术,无需插件支持,跨平台性能好;

缺点

Ajax 请求不修改浏览器历史记录,因此不支持前进后退功能;

Ajax 暴露了过多和服务器交互的细节;

破坏了程序的异常机制,容易调试;

不利于搜索引擎抓取信息;

同源策略

同源策略是Netscape提出的一个著名的安全策略,它是指同一个“源头”的数据可以自由访问,但不同源的数据相互之间都不能访问。我们试想一下以下几种情况:

1. 我们打开了一个天猫并且登录了自己的账号,这时我们再打开一个天猫的商品,我们不需要再进行一次登录就可以直接购买商品,因为这两个网页是同源的,可以共享登录相关的 cookie 或 localStorage 数据;

2. 如果你正在用支付宝或者网银,同时打开了一个不知名的网页,如果这个网页可以访问你支付宝或者网银页面的信息,就会产生严重的安全的问题。显然浏览器不允许这样的事情发生;

3. 想必你也有过同时登陆好几个 qq 账号的情况,如果同时打开各自的 qq 空间浏览器会有一个小号模式,也就是另外再打开一个窗口专门用来打开第二个 qq 账号的空间。

很明显,第1个和第3个例子中,不同的天猫商店和 qq 空间属于同源,可以共享登录信息。qq 为了区别不同的 qq 的登录信息,重新打开了一个窗口,因为浏览器的不同窗口是不能共享信息的。而第2个例子中的支付宝、网银、不知名网站之间是非同源的,所以彼此之间无法访问信息,如果你执意想请求数据,会提示异常:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

1

那么什么是同源的请求呢?同源请求要求被请求资源页面和发出请求页面满足3个相同:

协议相同

域名相同

端口相同

简单理解一下:

/*以下两个数据非同源,因为协议不同*/

http://www.abc123.com.cn/item/a.js

https://www.abc123.com.cn/item/a.js

/*以下两个数据非同源,因为域名不同*/

http://www.abc123.com.cn/item/a.js

http://www.abc123.com/item/a.js

/*以下两个数据非同源,因为主机名不同*/

http://www.abc123.com.cn/item/a.js

http://item.abc123.com.cn/item/a.js

/*以下两个数据非同源,因为协议不同*/

http://www.abc123.com.cn/item/a.js

http://www.abc123.com.cn:8080/item/a.js

/* 以下两个数据非同源,域名和 ip 视为不同源

* 这里应注意,ip和域名替换一样不是同源的

* 假设www.abc123.com.cn解析后的 ip 是 195.155.200.134

*/

http://www.abc123.com.cn/

http://195.155.200.134/

/*以下两个数据同源*/ /* 这个是同源的*/

http://www.abc123.com.cn/source/a.html

http://www.abc123.com.cn/item/b.js

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

Ajax

Ajax在编写时一共4个步骤:

创建 xhr 对象

设置传输地址

设置回调函数

发送数据

常见的发送方式有 GET 和 POST,除此之外还有 HEAD, DELETE, TRACE, PUT, CONNECT, OPTIONS和 PATCH等,这里只举例前两个 GET 和 POST。

例如根据姓名查询一个人的信息并写在div#output中

//GET 方法

function search(name, fun){

var xhr = new XMLHttpRequest();

var url = "search.php?name=" + window.encodeURIComponent(name) + "&t=" + Math.random();

xhr.open("GET", url);

xhr.send();

xhr.onreadystatechange = function(){

if(xhr.readyState == 4 && xhr.status == 200){

var data = JSON.parse(xhr.responseText); //获取了 JSON 字符串

fun(data);

}

}

}

function show(data){

this.innerHTML = "姓名:" + data.name + "
性别:" + data.gender + "
年龄:" + data.age + "
地址:" + data.address + "
电话:" + data.tel;

}

var output = document.getElementById("output");

search("李华", show.bind(output));

//服务器端 search.php

$name = $_GET[name];

//模拟数据查询结果

echo '{"name":"' . $name .'","age":18,"gender":"男","tel":"13211112222","address":"北京市海淀区xxxxxxxx"}';

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

//POST方法

function search(name, fun){

var xhr = new XMLHttpRequest();

var url = "search.php";

var para = "name=" + window.encodeURIComponent(name) + "&t=" + Math.random();

xhr.open("POST", url);

//POST方式下,必须把 Content-Type 设置为application/x-www-form-urlencoded

xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

xhr.onreadystatechange = function(){

if(xhr.readyState == 4 && xhr.status == 200){

console.log(xhr.responseText);

var data = JSON.parse(xhr.responseText); //获取了 JSON 字符串

fun(data);

}

}

xhr.send(para);

}

function show(data){

this.innerHTML = "姓名:" + data.name + "
性别:" + data.gender + "
年龄:" + data.age + "
地址:" + data.address + "
电话:" + data.tel;

}

var output = document.getElementById("output");

search("李华", show.bind(output));

//服务器端 search.php

$name = $_POST[name];

//模拟数据查询结果

echo '{"name":"' . $name .'","age":18,"gender":"男","tel":"13211112222","address":"北京市海淀区xxxxxxxx';

?>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

上述代码的 jQuery 写法:

//GET 方式

function search(name, fun){

var url = "search.php?name=" + window.encodeURIComponent(name) + "&t=" + Math.random();

$.get(url, fun);

}

function show(data){

data = JSON.parse(data);

this.innerHTML = "姓名:" + data.name + "
性别:" + data.gender + "
年龄:" + data.age + "
地址:" + data.address + "
电话:" + data.tel;

}

var output = document.getElementById("output");

search("李华", show.bind(output));

1

2

3

4

5

6

7

8

9

10

11

//POST 方式

function search(name, fun){

var url = "search.php";

var obj = {};

obj.name = name;

obj.t = Math.random();

$.post(url, obj, fun);

}

function show(data){

data = JSON.parse(data);

this.innerHTML = "姓名:" + data.name + "
性别:" + data.gender + "
年龄:" + data.age + "
地址:" + data.address + "
电话:" + data.tel;

}

var output = document.getElementById("output");

search("李华", show.bind(output));

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Ajax常见问题

缓存问题

细心一些可以发现,上面发送请求的数据中加入了一个随机数 t。因为有时服务器更新的了数据后,我们再一次执行 Ajax 请求不能显示新的结果,这是由于 js 为了加速,页面会使用缓存保持当前调用的相同链接。我们加了一个随机数以后,每次请求不同,浏览器就不会使用缓存数据了。

中文乱码问题

返回的中文数据乱码是因为 js 页面和action页面中使用了不同的编码方式导致的。可以有以下2中方式解决(浏览器 html 文件是 urf-8 编码的):

1. 对请求数据字段进行2次 encodeURI 编码,服务器获取数据后做一次 UTF-8 转码

2. 对请求数据字段进行1次 encodeURI 编码,服务器获取数据后做一次 ISO-8859-1 转换 和一次 UTF-8 转码

tips: 考虑到兼容性,第1个方法更好

兼容性问题

之前的代码并没有按兼容性的格式书写,不过 Ajax 的兼容也不难,主要表现在 XMLHTTPRequest对象获取环节:

var xhr;

if(XMLHttpRequest){

xhr = new XMLHttpRequest(); //chrome, safari, opera, firefox

} else if(ActionXObject){

try{

xhr = new ActionXObject("Msxml2.XMLHTTP"); //IE 中 Msxml 插件

}catch(e){

xhr = new ActionXObject("Microsoft.XMLHTTP"); //IE

}

}

1

2

3

4

5

6

7

8

9

10

GET和POST方式对比

GET

POST

后退/刷新

无害

数据会重新提交

书签

可藏为书签

无法藏为书签

缓存

可以缓存

不可以缓存

MIME类型

application/x-www-from-urlencode

application/x-www-from-urlencode或 multipart/form-data (二进制为多重编码

历史记录

参数保留在历史记录中

参数不会留在历史记录

数据长度

URL最长2048个字符(2kB)

无限

数据类型

ASCII字符

无限

安全性

可见性

数据可见

数据不可见

跨域数据访问

JSONP

这里需要强调的是,jsonp不属于Ajax的部分,它只是吧url放入script标签中实现的数据传输,主要优点是不受同源策略限制。由于一般库也会把它和Ajax封装在一起,所以这里放在一起讨论。下面是一个jsonp的例子(实现功能:输入手机号码查询归属地和运营商):

兼容问题

function jsonpCallback(data) {

document.getElementById('output').innerHTML = data.province + " " + data.catName;

}

document.getElementById('search').onclick = function(){

var num = document.getElementById('tel').value;

if(/^1[34578]\d{9}$/.test(num)){

var url = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=" + num + "t=" + Math.random() + "&callback=jsonpCallback";

var JSONP=document.createElement("script");

JSONP.type="text/javascript";

JSONP.src= url;

document.getElementsByTagName("head")[0].appendChild(JSONP);

} else {

alert("您输入的手机号有误")

}

};

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

上述代码的全部js部分可以用jQuery实现,如下:

function jsonpCallback(data) {

$('#output').text(data.province + " " + data.catName);

}

$('#search').click(function(){

var num = $('#tel').val();

if(/^1[34578]\d{9}$/.test(num)){

var url = "http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=" + num" + "t=" + Math.random();

$.ajax({

url: url,

type: 'GET',

dataType: 'JSONP', // 处理Ajax跨域问题(本质已不是Ajax)

success: function(data){

$('#output').text(data.province + " " + data.catName);

}

});

} else {

alert("您输入的手机号有误")

}

});

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

其他 Ajax 参数及方法

javascript

//属性

xhr.responseText; //从服务器返回的字符串数据

xhr.responseXML; //从服务器返回的 XML 数据

xhr.status; //服务器相应状态

xhr.readyState; //0: 请求未初始化; 1: 已建立连接; 2: 请求已接收; 3: 请求处理中; 4: 响应已就绪

xhr.timeout; //指定多少毫秒后超时,长整型

xhr.upload; //获取上传进度

xhr.withCredentials; //是否可以跨源,boolean 型,默认 false

//方法

xhr.getResponseHeader('connection'); //获取指定头信息

xhr.getAllResponseHeaders(); //获全部定头信息

xhr.open("METHOD", url, isAsyn); //open方法有3个参数,最后一个参数是 Boolean 型,表示是否异步,默认为 true

xhr.abort(); //终止请求,置xhr.readyState为0,但不触发onreadystatechange

xhr.overrideMimeType() //强制重写 http 头的 MIME 类型

//事件

XMLHttpRequestEventTarget.onreadystatechange //在xhr.readyState属性改变时触发

XMLHttpRequestEventTarget.ontimeout //在响应超时时触发

XMLHttpRequestEventTarget.onabort //当请求失败时调用该方法

XMLHttpRequestEventTarget.onerror //当请求发生错误时调用该方法

XMLHttpRequestEventTarget.onload //当一个HTTP请求正确加载出内容后返回时调用。

XMLHttpRequestEventTarget.onloadstart //当一个HTTP请求开始加载数据时调用。

XMLHttpRequestEventTarget.onloadend //当内容加载完成,不管失败与否,都会调用该方法

XMLHttpRequestEventTarget.onprogress //间歇调用该方法用来获取请求过程中的信息。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

注:关于 xhr.status 可能的返回值,详见 http状态码

jQuery 中的 Ajax 方法

ajax 静态方法

$.ajax({options}) //发起一个 ajax 请求

options 常用以下属性设置:url, method("GET"/"POST"), crossDomain, accepts(可接受的类型), dataType, cache, contentType(编码格式), success, error等

$.ajaxSetup({options}); //options同上,设置 ajax 默认参数,不建议使用

$.post(url, data, success, datatype); //发起一个 POST 请求 data为传递参数(可选), success(reponseText, statusText, xhr) 为成功时的回调函数(可选), datatype(xml/html/script/json/jsonp/text,可选)

$.get(url, data, success, datatype); //发起一个 GET 请求, 参数同上

$.getScript(url, data, success) //以 GET 请求获取一个 JS 文件并执行,参数含义同上

$.getJSON(url, data, success) //以 GET 请求获取一个 JSON 字符串,参数含义同上

1

2

3

4

5

6

7

ajax 动态方法

$().ajaxComplete(function(){}); //注册Ajax请求完成时要调用的处理程序

$().ajaxError(function(){}); //注册要在Ajax请求完成时遇到错误而调用的处理程序

$().ajaxSend(function(){}); //附加要在发送Ajax请求之前执行的函数

$().ajaxStart(function(){}); //注册在第一个Ajax请求开始时要调用的处理程序

$().ajaxStop(function(){}); //注册要在所有Ajax请求完成后调用的处理程序

$().ajaxSuccess(function(){}); //附加要在Ajax请求成功完成时执行的函数

$().load(url, data, callback); //返回某 url 的数据,data为传递参数(可选), callback(reponseText, statusText, xhr) 回调函数(可选)

1

2

3

4

5

6

7

其他相关方法

$.param(obj); //将对象转化为一个 url 参数列表

$(form).serialize(); //表单数据序列化为 url 参数列表

$(form).serializeArray(); //同上,但返回 JSON 串

1

2

3

简单封装 Ajax 相关方法

简单模仿 jQuery 中 $.ajax() 方法

(function(){

// Ajax 选项

var options = {

type: "GET", //提交方式

url: "", //路径

params: {}, //请求参数

dataType: "text", //内容类型

success: function(){}, //回调函数

error: function(){}

};

//获取 XMLHTTPRequest 对象

var createRequest = function(){

var xmlhttp;

if(xmlhttp.XMLHttpRequest){

xmlhttp = new XMLHttpRequest();

}

else{

xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');

}

if(xmlhttp.overrideMimeType){

xmlhttp.overrideMimeType('text/xml'); //修改 MIME 类型

}

return xmlhttp;

},

// 设定 Ajax 选项

var setOptions = function(newOptions){

for(var prop in newOptions){

if(newOptions.hasOwnProperty(prop)){

this.option[prop] = newOptions[prop];

}

}

},

//格式化参数列表

var formatParameters = function(){

var paramsArr = [];

var params = this.options.params;

for(var prop in params){

if(params.hasOwnProperty(prop)){

paramsArr.push(prop + "=" + encodeURIComponent(params[prop]));

}

}

return paramsArr.join('&');

},

//预处理并调用相应函数

var readystatechange = function(xmlhttp){

var returnValue;

if(xmlhttp.readyState == 4 && xmlhttp.status == 200){

switch(this.options.dataType){

case 'xml':

returnValue = xmlhttp.responseXML;

break;

case 'json':

returnVaue = xmlhttp.responseText;

if(returnValue){

returnValue = eval("(" + returnValue + ")");

}

break;

default:

returnVaue = xmlhttp.responseText;

break;

}

if(returnValue){

this.options.success(returnValue);

}

else{

this.options.success();

}

} else{

this.options.error();

}

},

//发送请求,也就是$.ajax()函数

var request = function(options){

// var ajaxObj = this;

var xmlhttp = this.createRequest();

this.setOptions(options);

xmlhttp.onreadystatechange = this.readystatechange.bind(null, xmlhttp);

var formatParams = this.formatParameters();

var type = this.options.type;

var url = this.options.url;

if("GET" === type.toUpperCase()){

url += "?" + formatParameters;

}

xmlhttp.open(type, url, true);

if("GET" === type.toUpperCase()){

xmlhttp.send();

} else if("POST" === type.toUpperCase()){

xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

xmlhttp.send(formatParameters);

}

}

window.$.ajax = request; //暴露方法到闭包外面去

})();

JavaScript JSON timer(计时器) AJAX HTTP请求 同源策略 跨域请求

JSON 介绍 1. JSON: JavaScript Object Notation 是一种轻量级的数据交换格式. 它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是 ...

JavaScript JSON AJAX 同源策略 跨域请求

网页和Ajax和跨域的关系 1 Ajax使网页可以动态地.异步地的与服务器进行数据交互,可以让网页局部地与服务器进行数据交互 2 Ajax强调的是异步,但是会碰到跨域的问题. 3 而有很多技术可以解决 ...

jQuery异步请求(如getJSON)跨域解决方案

相信大家在使用jQuery异步请求非自己网站内相对资源(通过别人站点上的URL直接读取)使经常会遇到如下错误吧,实际上这些错误都是浏览器安全机制“搞的鬼”,才让我们开发路上遇到了拦路虎. 当你直接在浏 ...

【手摸手,带你搭建前后端分离商城系统】02 VUE-CLI 脚手架生成基本项目,axios配置请求、解决跨域问题

[手摸手,带你搭建前后端分离商城系统]02 VUE-CLI 脚手架生成基本项目,axios配置请求.解决跨域问题. 回顾一下上一节我们学习到的内容.已经将一个 usm_admin 后台用户 表的基本增 ...

客户端ajax请求为实现Token验证添加headers后导致正常请求变为options跨域请求解决方法

客户端为了实现token认证,通过Jquery的ajaxSetup方法全局配置headers: 全局配置headers后会导致部分不需要token认证的请求变为options请求,导致跨域访问.报错信 ...

AJAX(XMLHttpRequest)进行跨域请求方法详解

AJAX(XMLHttpRequest)进行跨域请求方法详解(三) 2010年01月11日 08:48:00 阅读数:24213 注意:以下代码请在Firefox 3.5.Chrome 3.0.Saf ...

AJAX-同源策略 跨域访问

## 同源策略 概述: 同源策略是浏览器的一种安全策略,视为同源是指域名,协议,端口完全相同.只有同源的地址才可以通过AJAX方式请求.同源或者不同源说的是两个地址的关系,不同源地址之间请求我们称之为 ...

Django框架12 /同源、跨域、CORS

Django框架12 /同源.跨域.CORS 目录 Django框架12 /同源.跨域.CORS 1. 同源策略 2. 跨域 3. 解决跨域:CORS/跨域资源共享 1. 同源策略 同源策略(Same ...

ajax异步请求不能刷新数据的问题

搞了两三天的问题,今天解决了.总结下: function reportGrpChange(cuid, title){ document.getElementById('reportFrameDiv') ...

随机推荐

CentOS7中安装Python3.5

1.下载 https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tgz 2.上传到服务器 3. 安装相关依赖 yum install gcc ope ...

Application对象、Session对象、Cookie对象、Server对象初步认识

Application对象:记录应用程序参数的对象 用于共享应用程序级信息,即多个用户共享一个Application对象.在第一个用户请求ASP.NET文件时,将启动应用程序并创建Applicatio ...

Python单元测试框架之pytest -- fixtures

fixtures不太好翻译,可看作是夹心饼干最外层的两片饼干.通常用setup/teardown来表示.它主要用来包裹测试用例,为什么需要这样的饼干呢?我们以web自动化测试为例,例如,要测试的某系统 ...

HDFS主要特性和体系结构

引言 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统 ...

JDK的目录

要想深入了解Java必须对JDK的组成, 本文对JDK6里的目录做了基本的介绍,主要还是讲解 了下JDK里的各种可执行程序或工具的用途 Java(TM) 有两个平台 JRE 运行平台,包括Java虚拟 ...

jdbc 连接 oracle rac

jdbc 连接 oracle rac 的连接串如下:   jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = 192. ...

ABP之事件总线(2)

在上一篇文章中,我们复习了一下事件的经典的发布订阅模式,同时对是事件源和时间处理逻辑进行抽象统一,用起来也没有问题.但是还是有很多的问题,比如说我们Handle方法其实是违背了单一性的原则的,里面混杂 ...

021.8 properties(开发使用频率高)

内容:Properties基本存取.存储到持久化设备.从持久化设备读取.简单模拟收费软件试用结束##Properties——有配置文件的功能.    特点:    1.Hash table的子类,ma ...

php的基础知识(三)

12.函数: 函数的功能: 定义:在真实的项目开发过程中,有些代码会重复利用,我们可以把它提出来,做成公共的代码,供团队来使用,这个我们封装的代码段,就是函数(功能). 优点: 1.提高代码的利用率. ...

CentOS7下利用init.d启动脚本实现tomcat开机自启动

在之前的博文中已经对CentOS7下通过tomcat进行WEB系统的发布进行了介绍,今天将利用init.d启动脚本,将服务脚本加入到开机启动服务队列,实现tomcat服务的开机启动. 1. 环境准备 ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值