Ajax核心四步操作

AJAX

引入:你是如何理解AJAX的?

AJAX(Asynchronous Javascript And XML,异步JS和XML)。所谓异步JS指的是基于AJAX进行局部刷新。(全局刷新 vs 局部刷新)

服务器渲染时代(全局刷新):服务器收到HTTP请求,获取到请求的资源文件页面中的代码,从数据库中根据业务逻辑获取对应数据,混合到一起渲染。通过HTTP响应返回给客户端,浏览器只需要直接渲染就好了。服务器端要做的事情超多的,而且如果页面中某个部分数据需要动态更新,需要向服务器重新发请求,页面整体刷新一次。

客户端渲染时代(局部刷新):向服务器请求返回的只有结构index.html,某个部分需要更新时,再发一个AJAX请求拿到数据,通过JS动态填充到结构中。页面整体不刷新。但有一点不好,所有基于客户端渲染的内容,都不会在源代码中,这样也就不会被搜索引擎收录(搜不到),不利于SEO推广。

AJAX核心四步操作

  1. 创建一个XMLHttpRequest实例对象。
  2. 打开请求连接,配置请求信息。
  3. 监听请求状态——不同的状态做不同的事。
  4. 发送AJAX请求,AJAX任务开始,一直到响应主体信息返回代表任务结束。

XMLHttpRequest实例对象

let xhr = new XMLHttpRequest;     // 创建XMLHttpRequest实例对象

IE低版本浏览器中,使用new ActiveXObject创建对象。
想要扒一扒这个对象里都有啥属性 / 方法可以在浏览器控制台输出一下哦~

打开请求连接

/* @params:
 *   method:请求方法类型
 *   url:请求的文件在服务器上的位置
 *   async:true(异步)或 false(同步),一般都为默认值true
 */

xhr.open(method,url,async);

注意,open方法只是打开请求连接,并没有发送请求。

请求方法

GET系列 vs POST系列
GET与POST系列请求都可以在客户端和服务器之间往返,只不过在实际使用中,GET系列请求更倾向于从服务器获取(索取型人格),而POST系列请求更倾向于向服务器发送(付出型人格)。

GET系列请求包含:GET、HEAD(只获取响应头)、DELETE(一般指删除服务器上指定文件)、OPTIONS(试探性请求,常用于跨域请求)
POST系列请求包含:POST、PUT(与DELETE相对,向服务器新增文件)

基于两种方式向服务器发送请求,传递给服务器的方式:
① 都可以基于请求头发送。
② GET请求的主要方式是<mark style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">通过URL地址后的问号传参</mark>。
③ POST请求的需要方式是<mark style="box-sizing: border-box; outline: 0px; margin: 0px; padding: 0px; background-color: rgb(248, 248, 64); color: rgb(0, 0, 0); overflow-wrap: break-word;">基于请求主体发送</mark>。

正是由于这个区别,诞生了GET和POST系列的重要差异:

  • GET传给服务器的信息有大小限制——毕竟写在URL里,太长了会被自动截掉(相比大家都有这种体会);POST理论上是没有大小限制的,但实际项目中一般会手动进行限制,传的东西太笨重当然要尽量避免,会造成服务器压力过大,降低速度。
  • GET请求相对于POST不太安全,地址栏问号传参有被劫持的风险。但互联网中没有绝对的安全,涉及到对安全要求高的请求最好进行加密。
  • GET请求容易产生缓存(浏览器默认的),这个缓存我们经常是不想要的。若需要实时数据刷新,就不能走缓存。一般会在地址栏传参时添加一个随机数或时间戳,这样地址和参数不会完全一样就不会走缓存啦~ &_ = Math.random()。用_接收这个随机参数服务器会忽略掉。

举几个GET和POST请求的例子:

// get
let xhr = new XMLHttpRequest;
xhr.open('get','./data.json?lx=1&name=cmj');
xhr.send();

// post
let xhr = new XMLHttpRequest;
xhr.open('post','./data.json');
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send('lx=1&name=cmj');

// post请求的另一种类型
xhr.setRequestHeader('Content-Type','multipart/form-data');
let formData = new FormData();
formData.append('lx',2);
formData.append('name','szr');
xhr.send(formData);

说到这就有必要好好说一下xhr对象的setRequestHeader这个方法。

为啥要用到这个方法?通常在HTTP协议里,客户端向服务器取得某个网页的时候,必须发送一个HTTP协议的头文件,告诉服务器客户端要下载什么信息以及相关的参数。但默认的情况下有些参数可能没有说明在HTTP头里,当我们需要修改或添加这些参数时就用到了setRequestHeader 方法。

此方法必须在 open() 方法和 send() 之间调用。

/* @params:名值对 */
xhr.setRequestHeader(str,value);

get请求可以不用设置请求头,而post请求必须设置请求头。
那我们一般都会设置哪些请求头呢?最常用的就是Content-Type数据格式
传递给服务器的数据格式有:

Content-Type Description
application/x-www-form-urlencoded 最常用的方式,即xxx=xxx&xxx=xxx,在问号传参和post请求中一般都要求使用这种方式,结果是字符串类型
multipart/form-data 表单提交或文件上传时常用,结果是一个对象,参数以对象名值对的方式传递
raw text,json,xml,html等格式的文本,在富文本编辑器中的内容也可,结果是字符串类型
binary 二进制数据 / 编码格式数据

监听请求状态

这一步经常涉及到xhr对象的两个属性readyStatestatus和一个事件onreadystatechange()。当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。

AJAX状态码——xhr.readyState

状态码 含义
0 UNSEND未发送,当创建了一个XMLHttpRequest对象时状态码为0
1 OPENED已打开,xhr.open方法执行结束后状态码更新为1
2 HEADERS_RECEIVED,send请求发出后,接收到响应头信息
3 LOADING,响应主体信息回传中
4 DONE,接收到响应主体信息,AJAX任务结束

HTTP状态码——xhr.status

只列举常用的哦,想要了解全部请自行百度,一大堆。

状态码 含义
2xx 成功,操作被成功接收并处理
200 OK,希望看到的一种状态,但只代表在网络层面上成功接收,至于业务层面上是不是你想要的就不一定了,还需要前后端协商好数据判断标识。
3xx 重定向,需要进一步的操作以完成请求
301 Moved Permanently 永久重定向,比如这个域名不用啦,现在使用新的域名(但是同一个网站),当访问旧域名时就会永久重定向到新的域名下。
302 Move temporarily 临时重定向,一般用于服务器负载均衡
304 Not Modified 未修改。返回此状态码时,不会返回任何资源,而是让浏览器去获取缓存中的资源。
307 Temporary Redirect 临时重定向,与302傻傻分不清楚
4xx 客户端错误
400 Bad Request 客户端请求的语法错误,服务器无法理解
401 Unauthorized 未授权,没权限访问
403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
404 Not Found 您所请求的资源无法找到
405 Method Not Allowed 当前请求方式服务器不支持
5xx 服务器错误
500 Internal Server Error 服务器内部错误
503 Service Unavailable 服务器超负荷,比如春运抢票12306网站崩掉

不过在真实项目中,后台可能不按照这个规则处理,有可能都返回OK,然后在返回的JSON中,通过code标识错误信息。

在监听AJAX状态时进行的操作举例:

xhr.onreadystatechange(){
    let status = xhr.status,
        state = xhr.readyState,
        result = null;
    if(!/^(2|3)\d{2}/.test(status)){     // 如果返回的不是2xx或3xx开头的状态码,进行一些错误处理
        ...
        return;
    }
    if(state === 2){           // 响应头信息回来了
        console.log(xhr.getAllResponseHeaders());        // 获取所有的响应头信息
        console.log(xhr.getResponseHeader('data'));      // 获取指定的响应头信息
    }
    if(state === 4){    // 响应主体信息回来了
        result = xhr.response;        // 获取响应主体信息
    }
}

发送请求

xhr.send();

该方法的参数为请求主体;也就是说,GET请求的send方法不传参或传null,而POST请求才将请求主体作为send方法的参数。

注意:post请求要配合设置请求头。比如我设置了请求头中数据格式为application/x-www-form-urlencoded,但传递的请求主体又不是xxx=xxx&xxx=xxx这种字符串格式,它是不会进行自动转换的,我的请求头只是通知一下服务器而已,并没有对请求主体转换格式的能力!

那咋整?必须要进行参数序列化
可以引入Qs类库,使用Qs.stringify()转换为application/x-www-form-urlencoded格式,也可以自己封装一个参数序列化的方法嗷。具体来说,就是将{lx:1,name:'cmj'}转换为lx=1&name=cmj

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