龙空技术网

前端面试题——手写实现 ajax

前端琅琊阁 846

前言:

此刻看官们对“react怎么发ajax”可能比较关切,兄弟们都想要了解一些“react怎么发ajax”的相关文章。那么小编也在网上搜集了一些关于“react怎么发ajax””的相关内容,希望小伙伴们能喜欢,咱们快快来了解一下吧!

无论是通过模板引擎加载的,还是前后端分离的项目,我们都可以通过 ajax 来实现页面的无刷新请求数据。比如我们有个实时数据要展示,肯定是页面图表局部刷新,谁也不期待整个页面反复加载。

ajax 在我们的开发工作中已经司空见惯,几乎所有我们频繁使用的库和框架(如 jQuery、Vue、React)都提供了经过完善封装后的 ajax 方法,我们习惯于使用$ajax()、$axios、fetch来帮我们实现http请求数据,我们似乎忘记原生的该怎么写了。来吧,我们重温原理,温故而知新。

01

手写AJAX的步骤

手写ajax并没有一个统一的标准,一般的步骤是分以下几步:

创建XMLHttpRequest对象打开连接发送请求响应

也可以参照w3school:

02

步骤简要描述

1. 创建XMLHttpRequest对象

我们常用的 ajax 就是通过 XMLHttpRequest 对象实现的,这个对象有很多的属性和事件,在使用之前我们需要先将它实例化。

let xhr;if ((window as any).XMLHttpRequest) {  xhr = new XMLHttpRequest();} else {  //兼容IE  xhr = new ActiveXObject('Microsoft.XMLHTTP');}

2. 连接与发送

在通过send方法发送请求后,xhr 对象在收到响应数据时会自动填充到其对应的属性中,xhr 具有以下常用属性:

responseText:请求返回的数据内容

responseXML:如果响应内容是 "text/xml""application/xml",这个属性将保存响应数据的 XML DOM文档

status:响应的HTTP状态,如 200 304 404 等

statusText:HTTP状态说明

readyStatus:请求/响应过程的当前活动阶段

timeout:设置请求超时时间

//连接与发送let method=options.type.toUpperCase();if ('GET'===method) {  xhr.open('get', `${options.url}?${queryString}`, options.async);  xhr.send();} else if ('POST'===method) {  xhr.open('post', options.url, options.async);  xhr.send(options.data);}

3. 接收响应

readyStatus的值会随着请求各阶段的变化而改变,其一共有 5 个值:

xhr.readyStatus==0 尚未调用 open 方法

xhr.readyStatus==1 已调用 open 但还未发送请求(未调用 send)

xhr.readyStatus==2 已发送请求(已调用 send)

xhr.readyStatus==3 已接收到请求返回的数据

xhr.readyStatus==4 请求已完成

当readyStatus的状态发生改变时,会触发 xhr 的事件onreadystatechange,于是我们就可以在这个方法中,对接收到的数据进行处理

//接收xhr.onreadystatechange = () => {  if (xhr.readyState === 4) {    //clearTimeout(timer);    if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {      resolve(xhr.responseText);    } else {      reject(xhr.status);    }  }}

03

完整示例代码

1. 我们看一下完整代码

这里函数参数我采用了TypeScript, TypeScript使我们的代码可维护性和可读性变得非常好,本身的类型系统就是一个最好的文档,我们在编译阶段就可以发现错误。该 ajax 方法通过 我们上一篇文章提到的Promise A+ 规范的简单应用 方式实现回调。

interface Options {    url: string;    method?: string;    data: any;    timeout?: number;    headers?:object;    async?:boolean;}function toQueryString(params) {    let dataArr = [];    params.t = Math.random();    for (let key in params) {        dataArr.push(`${key}=${encodeURIComponent(params[key])}`);    }    return dataArr.join('&');}export function ajax(options: Options={method:'GET',data:{},url:'',timeout:10000,async:true}) {    return new Promise((resolve, reject) => {    	        if (!options.url) throw Error('the url is required!');        let xhr;        if ((window as any).XMLHttpRequest) {            xhr = new XMLHttpRequest();        } else {        	  //兼容IE            xhr = new ActiveXObject('Microsoft.XMLHTTP');        }         //请求参数拼接               const queryString=toQueryString(options.data);        const headers=options.headers||{'Content-Type':'application/json;charset=UTF-8'};                //请求头设置        Object.keys(headers).forEach(key=>{        	xhr.setRequestHeader(key,headers[key]);        })                //超时处理        xhr.timeout=options.timeout;        xhr.ontimeout=()=>{        	reject('请求超时');        }        //if (options.timeout) {        //    timer = setTimeout(() => {        //        xhr.abort();        //        reject('超时');        //    }, options.timeout)        //}                //连接与发送        let method=options.type.toUpperCase();        if ('GET'===method) {            xhr.open('get', `${options.url}?${queryString}`, options.async);            xhr.send();        } else if ('POST'===method) {            xhr.open('post', options.url, options.async);            xhr.send(options.data);        }            //接收        xhr.onreadystatechange = () => {            if (xhr.readyState === 4) {                //clearTimeout(timer);                if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {                    resolve(xhr.responseText);                } else {                    reject(xhr.status);                }            }        }    });}

04

如何使用

1. 使用方式

ajax({    url: 'your request url',    method: 'get',    async: true,    timeout: 1000,    data: {        test: 1,        aaa: 2    }}).then(res => {    console.log('请求成功: ' + res)}).catch(err=>{    console.error('请求失败: ' + err)})     

学无止境,觉得不错的话,请关注前端琅琊阁!

标签: #react怎么发ajax