day 21:ajax

ajax

概述:

ajax (asynchronous Javascript and xml )异步的Javascript 和 xml(传输格式为xml 但一般为JSON格式),主要用于请求对应的数据来渲染

数据请求流程 

 ajax的基础代码实现

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

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

xhr(xmlHttpRequest)的方法及属性

属性

  • readyState xhr 的状态
  • response 获取响应
  • responseText 获取响应文本
  • responseType 获取响应类型
  • 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 http.1.1新增的 (keep-alive 缓存当前连接 长连接)
User-Agent 浏览器相关版本信息
Referer 对应的请求的详细地址

 请求体 requestHeader(对应的请求头先被服务器接收 验证后在接收请求体)

post 请求将数据填充到请求体中(不可见)
请求体数据量大 发送的时候是分段发送的(后台获取的时候需要拼接获取)

响应相关

响应头(responseHeader)

Cache-Control 缓存控制器(强制缓存1.1新增)

expires 缓存控制(1.0)

Content-Type 响应内容的类型

Accpet-Control-Allow-Origin 设置跨域的响应头

last-modified 文件最后的修改时间(协商缓存)

etag  文件标识名(协商缓存)

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

http状态码(status)

取值范围在100-599内分别用对应的开头来表示对应的内容

 xhr的readyState

强制缓存和协商缓存 

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))
                }
            }
        }

promis版本

        //封装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、付费专栏及课程。

余额充值