原生Ajax总结

AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

AJAX技术的核心是XMLHTTPRequest对象(XHR),虽然名字中有XML,但是Ajax通信与数据格式无关。

创建XHR对象

IE7+、Firefox、Opera、Chrome 和Safari 都支持原生的XHR 对象,使用XMLHttpRequest构造函数。

var xhr=new XMLHttpRequest();//高版本

那么重点来了,我想要支持低版本的IE,那得怎么使呢,不着急,有妙招
首先检测原生XHR对象是否存在,如果存在则返回新实例。如果对象不存在,检查ActiveX对象。若都没有,那么,呵呵错误走你!

function createXHR() {
    if (typeof XMLHttpRequest != 'undefined') {
        return new XMLHttpRequest(); //高版本
    } else if (typeof ActiveXObject != 'undefined') { //IE低版本
        if (typeof arguments.callee.activeXString != 'string') {
            var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
                i, len;
            for (i = 0, len = versions.length; i < len; i++) {
                try {
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                } catch (ex) {
                    //跳过
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    } else {
        throw new Error('No XHR object available');
    }
}

使用XHR

在使用XHR对象时,必须调用open()方法,它有三个参数:要发送的请求类型(get、post)、请求的URL和表示是否异步。

xhr.open('get','dom.php',false);//对dom.php的get请求,false同步

open()方法并不会真正发送请求,而只是启动一个请求以备发送。通过send()方法进行发送请求,send()方法接受一个参数,作为请求主体发送的数据。如果不需要,必须填null,执行send()方法之后,请求就会发送到服务器上。

xhr.send(null);//发送请求

只能向同一个域中使用相同端口和协议的URL发送请求。如果URL与启动请求的页面有任何差别,都会引发安全错误。
当请求发送到服务器端,收到响应后,响应的数据会自动填充XHR对象的属性。共有四个属性:

属性名 说明
responseText 作为响应主体被返回的文本
responseXML 如果响应主体内容类型是‘text/xml’或'application/xml ,则返回包含响应数据的XML DOM文档。
status 响应的HTTP状态
statusText HTTP状态说明

接受响应之后,第一步检查status属性,以确定响应已经成功返回。一般200为成功。

已定义范围 分类
1xx 100-101 信息提示
2xx 200-206 成功
3xx 300-305 重定向
4xx 400-415 客户端错误
5xx 500-505 服务器错误
HTTP状态码 状态字符串 说明
200 ok 服务器成功返回了页面
301 永久转移
302 found 资源暂时转移,常用于短连接转长连接
304 Not Modified 请求的资源没有被修改,允许直接使用浏览器中缓存的版本
400 Bad Request 语法错误导致服务器不识别
401 Unauthorized 请求需要用户认证
403 Forbidden 拒绝提供服务,可能发生在用户没有输入验证码的情况下
404 Not found 指定的URL在服务器上找不到
500 Internal Server Error 服务器遇到意外错误,无法完成请求
502 Bad Gateway 网关错误
503 ServiceUnavaliable 由于服务器过载或维护导致无法完成请求
xhr.open("get", "example.txt", false);
xhr.send(null);
if((xhr.status>=200&&xhr.status<300)||(xhr.status==304)){
    alert(xhr.responseText);
}else{
    alert(alert("Request was unsuccessful: " + xhr.status);
}

以上同步调用,简单,但是真正需要的是异步调用。使用异步调用的时候,需要触发readystatechange事件,然后检测readyState的属性即可。

readyState值 状态 说明
0 未初始化 尚未调用open(方法)
1 启动 已经调用open()方法,但尚未调用send()方法
2 发送 已经调用send(),但尚未接受响应
3 接受 已经接受到部分响应数据
4 完成 已经接受到全部数据,而且可以使用
var xhr = createXHR();
xhr.onreadystatechange = function() {
        if (readyState === 4) {//异步监控
            if ((xhr.status >= 200 && xhr.status < 300) || (xhr.status == 304)) {
                alert(xhr.responseText);
            } else {
                alert(alert("Request was unsuccessful: " + xhr.status);
                }
            }
        };

xhr.open("get", "example.txt", true);//异步
xhr.send(null);

使用abort()方法可以取消异步请求,放在send()方法之前会报错。放在responseText
之前会得到一个空值。

get与post

首先来了解一下http头部信息,包含服务器返回的响应头信息和客户端发送出去的请求头信息。我们可以获取响应头信息或者设置 请求头信息。

名称 含义
Accept 浏览器能够处理的内容类型
Accept-Charset 浏览器能够显示的字符集
Accept-Encoding 浏览器能处理的压缩编码
Accept-Language 浏览器当前设置的语言
Connection 浏览器与服务器之间的连接类型
Cookie 当前页面设置的任何Cookie
Host 发出请求的页面所在的域
Referer 发出请求的页面的URL
User-Agent 浏览器的用户代理字符串
//使用getResponseHeader()获取单个响应头信息
alert(xhr.getResponseHeader('Content-Type'));
//使用getAllResponseHeaders()获取整个响应头信息
alert(xhr.getAllResponseHeaders());
//使用setRequestHeader()设置单个请求头信息
xhr.setRequestHeader('MyHeader', 'Lee'); //放在open 方法之后,send 方法之前

我们只可以获取服务器返回回来响应头信息,无法获取向服务器提交的请求头信息,自然定义的请求头,在Js端无法获取

get请求

get请求常用于向服务器查询某些信息。必要时,可以将查询字符串参数追加到URL的末尾,以便提交给服务器。
xhr.open('get','demo.php?rand='+Math.random()+'&name=koo',true)
通过URL后的问号给服务器传递键值对数据,服务器接收到返回响应数据。特殊字符
传参产生的问题可以使用encodeURIComponent()进行编码处理,中文字符的返回及传参,
可以将页面保存和设置为utf-8 格式即可。

function addURLParam(url, name, value){
    url+=(url.indexOf('?')==-1?'?':'&');//判断的url 是否有已有参数
    url+=encodeURLComponent(name)+'='+encodeURLComponent(value);
    return url;
}

post请求

post请求可以包含非常多的数据,我们在使用表单提交的时候,大多使用post传输方式。
xhr.open('post','demo.php',true);
而发送post请求的数据,不会跟在url的尾巴上,而是通过send()方法向服务器提交数据
xhr.send('name=lee&age=18')
一般来说,向服务器发送post请求由于解析机制的原因,需要进行特别的处理。因为post请求和web表单提交不同,需要使用XHR来模仿表单提交。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
从性能上来讲post请求比get请求消耗更多一些,用相同数据比较,get最多比post块2倍

封装ajax

function ajax(obj) {
var xhr = new createXHR();
obj.url = obj.url + '?rand=' + Math.random();
obj.data = params(obj.data);
if (obj.method === 'get') obj.url = obj.url.indexOf('?') == -1 ?
obj.url + '?' + obj.data : obj.url + '&' + obj.data;
if (obj.async === true) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) callback();
};
}
xhr.open(obj.method, obj.url, obj.async);
if (obj.method === 'post') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(obj.data);
} else {
xhr.send(null);
}
if (obj.async === false) {
callback();
}
function callback () {
if (xhr.status == 200) {
obj.success(xhr.responseText); //回调
} else {
alert('数据返回失败!状态代码:' + xhr.status + ',
状态信息:' + xhr.statusText);
}
}
}
//调用ajax
addEvent(document, 'click', function () { //IE6 需要重写addEvent
ajax({
method : 'get',
url : 'demo.php',
data : {
'name' : 'Lee',
'age' : 100
},
success : function (text) {
alert(text);
},
async : true
});
});
//名值对编码
function params(data) {
var arr = [];
for (var i in data) {
arr.push(encodeURIComponent(i) + '=' + encodeURIComponent(data[i]));
}
return arr.join('&');
}

新技术fetch

fetch 是全局量 window 的一个方法,它的主要特点有:
1、第一个参数是URL:
2、第二个是可选参数,可以控制不同配置的 init 对象
3、使用了 JavaScript Promises 来处理结果/回调:

fetch(url, options).then(function(response) { 
// handle HTTP response
}, function(error) {
 // handle network error
}).catch(fun)//c处理错误

fetch规范与jQuery.ajax()主要有两种方式的不同:
1、从 fetch()返回的 Promise 将不会拒绝HTTP错误状态, 即使响应是一个 HTTP 404 或 500。相反,它会正常解决 (其中ok状态设置为false), 并且仅在网络故障时或任何阻止请求完成时,它才会拒绝。
2、默认情况下, fetch在服务端不会发送或接收任何 cookies, 如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头).
fetch的使用更简单,通过promise异步机制来处理响应或错误,ajax的使用需要一步一步的调用很多方法
补充:Promise
Promise是异步编程的一种解决方案,该对象有两个特点:
1、对象的状态不受外界影响。有三种状态:PendingFulfilledRejected。只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2、一旦状态改变就不会在变。Promise状态的改变有两种:从Pending变为Fulfilled和从Pending变为Rejected。只要这两种情况发生,状态就不会再变。这是成为Resolved。
优点:1、可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回掉函数。
2、接口同意,控制异步操作更加容易
缺点:1、法取消Promise,一旦创建就会立即执行。
2、如果不设置回调函数,Promise内部抛出的错误不会反映到外部。
3、当处于Pending状态时,无法得知目前进展到哪一阶段

let promise=new Promise((resolve,reject)=>{
        resolve(str)
        reject('err')
})
promise.then((str)=>{
    console.log(str)//这个是resolve的回调
},(reject)=>{
     console.log(reject)//这个是reject的回调
})

参考资料:JavaScript高级程序设计(第3版)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容