使用XHR和Promise简易实现Axios

用XHR和Promise模拟Axios

1.介绍        

1.1XHR介绍

        XMLHttpRequest(XHR)是一种浏览器提供的API,用于在客户端和服务器之间发送HTTP或HTTPS请求,支持异步数据传输。它是AJAX(Asynchronous JavaScript and XML)技术的核心,允许网页在不重新加载的情况下更新部分内容。

XHR的主要特点包括:

  • 支持异步和同步请求(默认异步)。
  • 可以发送各种HTTP方法(GET、POST、PUT、DELETE等)。
  • 能够处理多种数据格式(JSON、XML、文本等)。
  • 提供事件监听机制(如onloadonerroronprogress

基本用法示例

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true); // 异步请求
xhr.onload = function() {
  if (xhr.status === 200) {
    console.log(xhr.responseText);
  } else {
    console.error('请求失败');
  }
};
xhr.onerror = function() {
  console.error('请求出错');
};
xhr.send();
 

1.2Promise 介绍

Promise是JavaScript中用于处理异步操作的对象,代表一个可能现在、将来或永远不可用的值。它解决了回调地狱(Callback Hell)问题,使异步代码更易读和维护。

Promise的三种状态:

  1. Pending(进行中):初始状态,未完成或拒绝。
  2. Fulfilled(已成功):操作成功完成。
  3. Rejected(已失败):操作失败或被拒绝。

基本用法示例

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('数据加载成功');
    } else {
      reject('数据加载失败');
    }
  }, 1000);
});

fetchData
  .then((result) => {
    console.log(result); // 输出:数据加载成功
  })
  .catch((error) => {
    console.error(error); // 输出:数据加载失败
  });
 

1.3Axios介绍

        Axios 是一个基于 Promise 的 HTTP 客户端,专为浏览器和 Node.js 设计。它支持拦截请求和响应、转换请求和响应数据、自动转换 JSON 数据,并提供客户端防御 XSRF 的功能。

支持 Promise API
axios 的所有请求均返回 Promise 对象,支持链式调用和 async/await 语法,简化异步操作。

拦截请求和响应
可以通过拦截器在请求发送前或响应返回后统一处理数据,例如添加全局 headers 或错误日志。

自动转换数据
请求数据(如 POST)和响应数据(如 JSON)会自动转换格式,无需手动处理。支持 ArrayBufferFormData 等数据类型。

取消请求
使用 CancelToken 或 AbortController 取消正在进行的请求,适用于组件卸载时中止冗余请求。

基本用法示例 

        接下来将使用XHR和Promise将对无参请求、参数请求、Json格式的Post请求等进行简易实现。

//无参请求
axios({
    method: 'get',
    url: 'http://ajax-api.itheima.net/api/province',
}).then((response)=>{
    console.log(response)
})
//查询参数请求
axios({
    method: 'get',
    url: 'http://ajax-api.itheima.net/api/city',
    params:{
        pname:'辽宁省'
    }
}).then((response)=>{
    console.log(response)
})
//post请求
axios({
    method: 'post',
    url: 'http://ajax-api.itheima.net/register',
    data:{
        username:'张三',
        password:'123456'
    }
}).then((response)=>{
    console.log(response)
})

2.实现

2.1无参请求

axio的无参请求传入了对象作为配置。配置其method、url、params和data等,因此myAxios传入config来作形参配置。

//无参请求
axios({
    method: 'get',
    url: 'http://ajax-api.itheima.net/api/province',
}).then((response)=>{
    console.log(response)
})

代码中promise的resolve和then是对应的,reject和catch是对应的。目前代码中执行执行无参请求。

function myAxios(config){                     //config配置形参
    return new Promise((resolve,reject)=>{    //返回promise对象用于管理异步任务及其结果
        let xhr=new XMLHttpRequest();         //创建xhr对象
        xhr.open('GET',config.url);           //配置method和url
        xhr.addEventListener('loadend',()=>{  //对xhr对象添加监听事件
            if(xhr.status>=200 & xhr.status<300){
                resolve(xhr.response)        //如果请求成功,则执行为promise设置的then方法将data作为参数传入。
            }else{
                reject(new Error('请求失败')) //如果请求失败,则执行catch方法,同样传参。
            }
        })
        xhr.send();                           //发送请求
    })
}
let ax=myAxios({
    url:'http://ajax-api.itheima.net/api/province'
}).then((result)=>{
    console.log(result) //成功执行这个函数
}).catch((error)=>{
    console.log(error)  //失败执行这个函数
})
console.log(ax)

2.2参数请求

axios中传入了params对象作为查询参数。

//查询参数请求
axios({
    method: 'get',
    url: 'http://ajax-api.itheima.net/api/city',
    params:{
        pname:'辽宁省'
    }
}).then((response)=>{
    console.log(response)
})

查询参数是URL中用于向服务器传递额外信息的键值对,通常出现在问号? 之后,格式为 key=value,多个参数用 &连接。例如:

//http://ajax-api.itheima.net/api/city?city=XX&province=xx

有两种方法,使用URLSearchParams来接收params对象.toString()将对象转为需要的查询参数字符串。当然可以采用方法二自己来实现。

params={
    pname:'河北省'
}
//方法一
let urlParams=new URLSearchParams(params)
let urlStr='?'+urlParams.toString()
console.log(urlStr)//pname=%E6%B2%B3%E5%8C%97%E7%9C%81 这是url编码

//方法二
let arr=[];
for(let key in config.params){
    arr.push(`${key}=${config.params[key]}`)
}
config.url+='?'+arr.join('&')

进行修改后

function myAxios(config){
    return new Promise((resolve,reject)=>{
        let xhr=new XMLHttpRequest();

        //修改部分
        let urlStr=''
        if(config.params){
            let urlParams=URLSearchParams(config.params)
            urlStr='?'+urlParams.toString()
        }
        xhr.open('GET',config.url+urlStr);


        xhr.addEventListener('loadend',()=>{
            if(xhr.status>=200 & xhr.status<300){
                resolve(xhr.response)
            }else{
                reject(new Error('请求失败'))
            }
        })
        xhr.send();
    })
}

2.3请求体请求

HTTP 请求方法

HTTP 协议定义了多种请求方法,用于执行不同的操作。以下是常见的 HTTP 请求方法及其用途:

GET
用于请求指定资源的数据。GET 请求通常用于检索信息,不应修改服务器上的数据。GET 请求的参数会附加在 URL 中。

POST
用于向服务器提交数据,通常用于表单提交或上传文件。POST 请求的数据包含在请求体中,而不是 URL 中。

PUT
用于更新服务器上的资源。PUT 请求会替换目标资源的全部内容。如果资源不存在,PUT 可能会创建它。

DELETE
用于删除服务器上的指定资源。


通过修改open函数参数,||运算符会返回第一个为真的内容,如果method为空则为假,会采用GET请求。这样就可以根据传入的method来更改请求方法。

xhr.open(config.method||'GET',config.url);

  如果有传入的data则,先设置请求头的内容类型,再将data转为json格式发送出去。

function myAxios(config){
    return new Promise((resolve,reject)=>{
        let xhr=new XMLHttpRequest();
        let urlStr=''
        if(config.params){
            let urlParams=URLSearchParams(config.params)
            urlStr='?'+urlParams.toString()
        }
        xhr.open(config.method||'GET',config.url+urlStr);
        xhr.addEventListener('loadend',()=>{
            if(xhr.status>=200 & xhr.status<300){
                resolve(xhr.response)
            }else{
                reject(new Error('请求失败'))
            }
        })

         //修改部分
        if(config.data){ //如果有data则,设置请求体的内容类型为json
            xhr.setRequestHeader('Content-Type','application/json')
            xhr.send(JSON.stringify(config.data))//所以要将对象转为json进行发送
        }else{
            xhr.send();
        }


    })
}

data={
    username:'张三',
    password:'123456'
}
myAxios({
    method:'POST',
    url:'http://ajax-api.itheima.net/register',
    data
}).then((result)=>{
    console.log(result)
}).catch((error)=>{
    console.log(error)
})

以下是走到了catch中的结果。

更改username为李四的成功结果。


以上便是对Axios部分功能的简单实现,之后还可以继续进行内容的丰富。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值