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请求的主要方式是通过URL地址后的问号传参
③ POST请求的需要方式是基于请求主体发送

正是由于这个区别,诞生了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

你可能感兴趣的:(Ajax核心四步操作)