day22 Ajax

文章详细介绍了Ajax的基本原理,包括如何创建XMLHttpRequest对象、发送GET和POST请求,以及处理HTTP状态码和缓存机制。同时,文章还展示了使用回调函数和Promise封装的Ajax请求方法。
摘要由CSDN通过智能技术生成

概述:

ajax(asyncchronous JavaScript and xml)异步的JavaScript和xml(传输格式为xml但一般为json),它主要是用于请求对应的数据来帮助渲染的.

数据请求流程

ajax的基础代码实现 

核心对象(xmlHttpRequest(简称xhr))

//实例化请求对象
        var xhr = new XMLHttpRequest()
        //建立连接 (请求方式 get请求(能看到) post请求(看不到))
        xhr.open(请求方式,地址)
        //发送请求
        xhr.send()
        //监听请求的变化 readystate(状态值 xhr独有的)
        xhr.onreadystatechange = function(){
            //在监听的处理函数内接收相应数据
            //判断是否有数据成功返回 readystate0-4
            //(0 请求未发送 1 请求准备发送 2请求发送成功 3请求成功 响应中 4请求成功 响应成功)
            if(xhr.readyState == 4&& /^2\d{2}$/.test(xhr.status)){
                console.log(xhr.responseXML)//接收xml
                console.log(xhr.responseText)//接收文本 字符串
            }
        }

xhr(xmlHttpRequest)的方法及属性

属性

  • readyState xhr的状态值
  • response 获取响应
  • reponseText获取响应文本
  • responceType获取响应类型
  • responseURL 获取响应地址
  • responseXML 获取相应的xml
  • status 获取http的状态文本(后台返回的)
  • timeout 超时时间(设置的)

方法 

  • upload(返回一个上传对象 (XMLHttpRequestUpload))
  • open打开一个连接(传入对应的请求方式和地址)
  • send 发送一个请求(内部传入的是请求体的内容)
  • getAllResponseHeaders  获取所有的响应头(返回的是字符串)
  • getResponseHeader 获取指定响应头 (传入对应响应头的名字)
  • XMLHttpRequest的overrideMimeType方法是指定一个MIME类型用于替代服务器指定的类型,使服务端响应信息中传输的数据按照指定MIME类型处理.例如强制使用方式处理为"text/xml"类型处理时会被使用到 即使服务器在响应头中并没有这样指定
  • setRequestHeader 设置请求头(里面传入对应的请求头名字和对应的值)

事件

  • onreadystateChange readyState的值发生变化的时候调用
  • ontimeout 超时之后调用的 

后台接口返回具备的三个内容(响应) 

  • 状态码(status)
  • 状态文本(相关信息statusText)
  • 数据(data)

请求和响应的组成 

请求相关

  • 请求头requestHeader(对应的请求头先被服务器接收 验证后再接收请求体)
    //常用请求头
    //Content-type 请求的内容的类型
    //Cookie cookie存在于请求头
    //Connection http1.1新增的(keep-alive 缓存当前连接 长连接)
    //user-Agent浏览器相关版本信息
    //Referer 对应的请求的详细地址
  • 请求体requestBody
    poet 请求将数据填充到请求体(不可见得)
    请求体数据量大 发送的时候是分段发送的(后台获取的时候需要拼接获取)

响应相关

响应头(responseHeader)

  • Cache-Control缓存控制器(强制缓存1.1新增的)
  • expiries缓存控制(1.0)
  • Content-Type响应内容的类型
  • Accpet-Control-Allow-Origin 设置跨域的响应头
  • last-modified 文件最后修改的时间(协商缓存)
  • etag 文件标识名(协商缓存)

响应体(数据 状态码 状态文本)responseBody

http状态码(status)

主要取值为100-599内 分别用对应的开头来表示对应的内容

开头状态码含义常用状态码
1开头表示成功但是需要下一步操作100
2开头表示成功200
3开头表示重定向304,303
4开头表示客户端错误404,401,402,403,400
5开头表示服务端错误500,501

xhr的readystate

readyState取值含义
0请求未发送
1请求准备发送
2请求发送成功
3请求成功响应中
4请求成功 响应完成

强制缓存和协商缓存

http的缓存

为了节省对应的资源,减少对应的请求,产生了缓存.缓存相当于下载 也就是说如果缓存了那么就不需要再请求对应的服务器了

强制缓存(对应的内容强制被缓存 没有请求的发送)

  • cache-control来控制
cache-control:no-cache//开启强制缓存 no-storage不开启强制缓存
cache-control:MaxAge(9000)//规定时间内使用强制缓存
cache-control:public //一定缓存(第三方代理缓存)
cache-control:private//看客户端的处理

协商缓存(不使用强制缓存 才会采用协商缓存)

  • last-modified  最后修改时间
  • etag 文件标识名

如果这个文件在访问的时候是a文件 你第二次访问的时候 我将a文件进行了修改那么对应的last-modified就会发生更改 那么就会进行数据的重新请求,如果没有进行修改,那么这个时候对应的a文件还是a文件 那么我就需要比对a文件是否是a文件(etag来比对),如果是那么不进行缓存,如果不是重新请求.

协商缓存一定要发送请求 如果被缓存那么对应的状态码为304 如果没有缓存那么就是一个新的请求(如果成功就是200)
总结

  • 优先使用强制缓存 如果没有强制缓存 使用协商缓存
  • 如果强制缓存了 那么协商缓存就不会被使用 且不会有请求发送
  • 如果没有强制缓存那么对应的协商缓存就会触发 主要比对的是最后修改时间和对应的文件标识 如果都比对成功那么就是使用协商缓存 如果没有比对上那么就不会缓存.
  • 如果协商缓存成功那么对应的状态码为304 如果协商缓存失败那么对应的状态码就是一个新请求的状态码(成功就是200)
  • 强制缓存使用对应的响应头的cache-control来控制 协商缓存使用响应头的etag和last-modified来控制
  • 强制缓存没有请求 协商缓存必须请求

get和post请求 

get请求(获取数据)

  • get请求一般用于获取数据(安全性低 效率高  速度快)
  • 默认的请求方式为get请求(没有设置对应的请求就是get请求)
  • 传输的参数利用?进行拼接 拼接到对应的url
  • get请求会默认缓存对应的参数
  • 传输的参数会在请求头中
  • get请求传输的数据大小有限制(2kb)

post请求(文件上传 登录 注册...)

  • post请求的数据(封装为一个表单对象)在请求体中
  • post请求相对get要安全
  • post请求的数据量大于get(数据没有大小限制)
  • post请求的数据不会被缓存
  • post请求必须手动设置为post请求

get请求的封装

回调函数

//封装get请求的方法
function get(params = {}, callback) {
//判断是否传入url
if (!params.url) {
throw new Error('必须传入url地址')
}
//创建xhr对象
var xhr = new XMLHttpRequest()
//参数和baseUrl进行拼接
let baseURL = params.url
//遍历参数对象
for (var key in params) {
if (key != 'url') {
//判断是否存在?
// 如果没有前面带?
// 如果有前面带&
let s = baseURL.includes('?') ? '&' : '?'
baseURL += `${s+key}=${params[key]}`
}
}
//打开连接
xhr.open('get', baseURL)
//发送请求
xhr.send()
//监听事件
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
//调用回调函数 进行相关操作 传入对应的返回的数据
callback(JSON.parse(xhr.responseText))
}
}
}

promise版本

//封装get请求的方法 利用promise来解决
export function get(params = {}) {
//判断是否传入url
if (!params.url) {
throw new Error('必须传入url地址')
}
//创建xhr对象
var xhr = new XMLHttpRequest()
//参数和baseUrl进行拼接
let baseURL = params.url
//遍历参数对象
for (var key in params) {
if (key != 'url') {
//判断是否存在?
// 如果没有前面带?
// 如果有前面带&
let s = baseURL.includes('?') ? '&' : '?'
baseURL += `${s+key}=${params[key]}`
}
}
//打开连接
xhr.open('get', baseURL)
//发送请求
xhr.send()
//返回一个新的promise
return new Promise((resolve, reject) => {
//监听事件
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
//调用resolve传递数据 给then
resolve(JSON.parse(xhr.responseText))
}
}
})
}

post请求

基础post请求

//创建xhr
var xhr = new XMLHttpRequest()
//打开连接
xhr.open('post', 'https://jsonplaceholder.typicode.com/posts')
//设置请求头 告诉服务器发送的数据是表单 x-www-form-urlencoded 表示发送的表单数据
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
//发送请求 请求体 name=张三&age=18
xhr.send("name=张三&age=18")
//监听
xhr.onreadystatechange = () => {
//接收数据处理
console.log(xhr.responseText)
}
  • post请求数据发送使用send函数携带 (post请求携带到对应的请求体中)
  • 在发送之前要指定对应的请求头 content-type :application/x-www-form-urlencoded (指定数据类型为表单)

回调函数的封装

//封装post请求的方法
function post(params = {}, callback) {
//判断是否传入url
if (!params.url) {
throw new Error('必须传入url地址')
}
//创建xhr对象
var xhr = new XMLHttpRequest()
//参数和baseUrl进行拼接
let baseURL = params.url
let paramString = ""
//遍历参数对象
for (var key in params) {
if (key != 'url') {
let s = paramString?'&':""
paramString += `${s+key}=${params[key]}`
}
}
//打开连接
xhr.open('post', baseURL)
//发送请求
//设置请求头
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send(paramString)
//监听事件
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
//调用回调函数 进行相关操作 传入对应的返回的数据
callback(JSON.parse(xhr.responseText))
}
}
}

promise的封装

//封装post请求的方法
export function post(params = {}) {
//判断是否传入url
if (!params.url) {
throw new Error('必须传入url地址')
}
//创建xhr对象
var xhr = new XMLHttpRequest()
//参数和baseUrl进行拼接
let baseURL = params.url
let paramString = ""
//遍历参数对象
for (var key in params) {
if (key != 'url') {
let s = paramString?'&':""
paramString += `${s+key}=${params[key]}`
}
}
//打开连接
xhr.open('post', baseURL)
//发送请求
//设置请求头
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send(paramString)
//监听事件
return new Promise((resolve,reject)=>{
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
//调用回调函数 进行相关操作 传入对应的返回的数据
resolve(JSON.parse(xhr.responseText))
}
}
})
}

get请求和post请求的联合封装

export default class Ajax {
//传入的是根路径 传入超时时间
constructor(url, time) {
this.baseURL = url
this.timeout = time
}
//创建一个请求对象的方法
static createRequest(option) {
let defaultOption = {
baseURL: "",
timeout: 3000
}
//根据对应的option来进行比对 如果option有就使用option的内容来替换对应的defaultOption
for (var key in option) {
defaultOption[key] = option[key]
}
//读取对应的配置 返回一个ajax对象
return new Ajax(defaultOption.baseURL, defaultOption.timeout)
}
//准备对应的request方法 {url,contentType,method,data}
request(requestConfig) {
//method要传递 url也要传递 data也要传递
if (requestConfig.url == undefined ||
(requestConfig.method.toLowerCase() != 'get' &&
requestConfig.method.toLowerCase() != 'post') ||
!requestConfig.data
) {
throw new Error()
}
//默认就是以表单提交
requestConfig.contentType = requestConfig.contentType ?
requestConfig.contentType : 'application/x-www-form-urlencoded'
//准备xhr对象
let xhr = new XMLHttpRequest()
//设置对应的timeout
xhr.timeout = this.timeout
//url
let url = this.baseURL + requestConfig.url
//get数据的拼接 拼接到url
if (requestConfig.method.toLowerCase() == 'get') {
for (var key in requestConfig.data) {
if (url.includes('?')) {
url += `&${key}=${requestConfig.data[key]}`
} else {
url += `?${key}=${requestConfig.data[key]}`
}
}
}
//打开连接
xhr.open(requestConfig.method, url)
//设置请求头
if (requestConfig.method.toLowerCase() == 'post') {
xhr.setRequestHeader('content-type', requestConfig.contentType)
}
//post数据拼接
if (requestConfig.method.toLowerCase() == 'post') {
var paramsString = ""
for (var key in requestConfig.data) {
if (!paramsString) {
paramsString += `${key}=${requestConfig.data[key]}`
} else {
paramsString += `&${key}=${requestConfig.data[key]}`
}
}
}
//发送数据
xhr.send(paramsString)
//监听
return new Promise((resolve, reject) => {
xhr.onreadystatechange = () => {
//判断
if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
resolve(JSON.parse(xhr.responseText))
}
}
})
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值