day22 ajax

概述 :

AJAX (asynchronous javaScript and xml ) 是异步的JavaScript和xml . 它是用于发送http请求的 , 也可以发送异步和同步请求 , 它的特点是可以完成页面的局部刷新功能 ( 在整个页面不刷新的前提下 , 发送对应的请求改变对应的部分的dom ) , 它的核心对象是XMLHTTPRequest ( xhr )

  • 是一种服务器和浏览器进行 "通讯" 的技术 ,

    可以实现局部刷新 ( 降低了服务器的压力 , 提高了页面渲染速度 , 减少重绘和回流提高用户体验)

  • 为什么使用ajax ? - 为了提高用户体验
ajax的异步是怎么获取到数据的 ?
  • 使用了onreadystatechange事件 , 并结合callback回调函数取值来解决异步

  • ajax的同步,会在发送请求时占据主线程 造成阻塞 , 不推荐使用 ( js引擎是单线程的,同步会造成阻塞 )

关键词 :

  • 线程 : 线程是进程的最小单位 , JavaScript是单线程的语言 ( 单线程解析 , 渲染线程也是单线程 )

  • 进程 : 正在运行的程序

  • 同步 : 同一个线程执行 , 会造成同步阻塞 ( 上一个线程没有做完 , 下一个就不能执行 )

  • 异步 : 多个线程 ( 上一个线程和这一个线程没有关系 )

请求流程 :

 

ajax的代码实现

复制代码
//1.新建请求对象
var xhr=new XMLHttpRequest()
//2.设置请求地址和请求方式
xhr.open('get','请求地址')
//3.发送请求
xhr.send()
//4.监听请求状态的变化 readystate(0-4,0是什么都没做,1准备发送,2发送完成,3发送完成数据准备接收,4数据接收完毕(响应完成),5是错误)
xhr.onreadystatechange = ()=>{
    //进行判断对应的状态 
    if(xhr.readyState==4){
        //responseText返回的文本是字符串
        console.log(xhr.responseText)
    }
}
复制代码

XMLRequest对象的相关属性及方法

属性 :

  • readyState 状态码

  • status http状态码

  • timeout 超时时间

  • responseText 响应文本

方法 :

  • open() 打开一个请求

  • send() 发送请求

  • setRequestHeader() 设置请求头

  • getResponseHeader() 获取响应头

事件 :

  • onreadystatechange=()=>{}

复制代码
var xhr = new XMLHttpRequest()
// 属性
//1.readyState 对应的xhr对应的状态码(这个状态码只有xhr才有)
console.log(xhr.readyState)
//2.status http状态码 (只要发送http请求都会有)
//取值为100-599
//1开头(表示成功,但是需要后续操作) , 
// 2开头(数据请求成功 ,一般是200) , 
// 3开头(重定向,304重新定义方向,就是去了别的页面) , 
// 4开头(客户端错误,404找不到页面,403访问权限不足) ,
// 5开头(服务器错误,500) 跟前端无关系
console.log(xhr.status)
//3.responseText 响应的文本
console.log(xhr.responseText)
//4.responseXML 响应的xml
console.log(xhr.responseXML)
//responseType 响应类型
console.log(xhr.responseType)
//responseURL 响应地址
console.log(xhr.responseURL)
// 设置请求的超时事件
console.log(xhr.timeout)

// 方法
// 设置请求 open 请求方式,请求地址
xhr.open('get', '请求地址')
// 发送请求 可传参,参数是设置给请求体的内容
xhr.send('')
// 设置请求头,通过键值对的方式(2个参,都是字符串)
xhr.setRequestHeader()
// 响应头获取,根据key获取值
xhr.getResponseHeader('Content-type')

// 事件 当前状态改变的事件
xhr.onreadystatechange = () => {
    // 判断readyState为4并且http状态码以2开头
    if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
        console.log('世界')
    }
}
console.log('你好')
复制代码

数据渲染案例

复制代码
<button>请求数据</button>
<ul></ul>
<script>
    // 获取ul
    let ul = document.querySelector('ul')
    // 给按钮添加点击事件
    document.querySelector('button').onclick = () => {
        // 创建请求对象
        let xhr = new XMLHttpRequest()
        // 设置请求方式和地址
        // get请求传参使用?和&做拼接,第一个前面要加?,多个参数使用&连接
        xhr.open('get', 'http://jsonplaceholder.typicode.com/todos')
        // 发送数据
        xhr.send()
        // 监听状态变化
        xhr.onreadystatechange = () => {
            // 如果状态码都是正常的
            if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
                // 那么先将字符串转为对象
                let result = JSON.parse(xhr.responseText)
                // 再遍历进行渲染
                result.forEach((item) => {
                    ul.innerHTML += `
<li>
id:${item.id}
${item.title}
${item.completed ? '💓' : '💔'}
    </li>
`
                })
            }
        }
    }
</script>
复制代码

get请求封装

复制代码
// 封装一个get方法 ,url请求地址,params参数(以对象传递),callback对应的处理方式
function get(url, params = {}, callback) {
    // 如果没有填url就直接报错
    if (!url) {
        throw new Error('url必须填写')
    }
    // 创建请求对象
    let xhr = new XMLHttpRequest()
    // 设置请求方式和地址
    // 先遍历参数
    for (let key in params) {
        // 判断url地址是否存在?没有就加在前面,有就在前面加&
        if (!url.includes('?')) {
            url += `?${key}=${params[key]}`
        } else {
            url += `&${key}=${params[key]}`
        }
    }
    xhr.open('get', url)
    // 发送数据
    xhr.send()
    // 监听状态变化
    xhr.onreadystatechange = () => {
        // 判断是否成功
        if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
            // 成功就调用回调函数传递参数
            // 先转成对象再传递
            callback(JSON.parse(xhr.responseText))
        }
    }

}
复制代码

分页渲染实例

复制代码
<nav aria-label="Page navigation">
    <ul class="pagination">
        <li><a href="#">1</a></li>
        <li><a href="#">2</a></li>
        <li><a href="#">3</a></li>
        <li><a href="#">4</a></li>
        <li><a href="#">5</a></li>
    </ul>
</nav>
<ul class="content"></ul>
<script type="module">
    // 导入封装的get方法
    import { get } from './00.js'
    // 获取按钮和显示区域
    let lis = document.querySelectorAll('.pagination li a')
    let ul = document.querySelector('.content')
    // 给每个按钮添加点击事件
    Array.prototype.forEach.call(lis, ((item, index) => {
        item.onclick = () => {
            // 调用get方法,传入地址,参数和处理方法进行渲染
            get('http://jsonplaceholder.typicode.com/todos', {
                _limit: 10,
                _page: index+1
            }, (res) => {
                ul.innerHTML=''
                res.forEach((item)=>{
                    ul.innerHTML+=
                        `<li>
                        id:${item.id},
                        ${item.title},
                        ${item.completed?'💙':'💚'}    
                        </li>`
                })
            })
        }
    }))
</script>
复制代码

简单的post请求

复制代码
<form action="https://jsonplaceholder.typicode.com/posts" method="post">
    <input type="text"><br>
    <input type="password"><br><br>
    <button type="submit">登录</button>
</form>
<script>
    // 获取form表单并添加提交事件
    document.forms[0].onsubmit = () => {
        // 获取input框的内容
        let inputs = document.querySelectorAll('input')
        let uname = inputs[0].value
        let upwd = inputs[1].value
        // 创建请求对象
        let xhr = new XMLHttpRequest()
        // 设置请求方式和地址
        xhr.open('post', "https://jsonplaceholder.typicode.com/posts")
        // 设置请求头
        xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
        // 发送数据
        xhr.send(`uname=${uname}&upwd=${upwd}`)
        // 监听状态变化
        xhr.onreadystatechange = (e) => {
            // 阻止默认行为
            e = e || window.event
            e.preventDefault()
            // 判断是否成功
            if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
                console.log(xhr.responseText)
            }
        }
    }
</script>
复制代码

post请求封装

复制代码
// post请求封装
export function post(url, params = {}, callback) {
    // 判断url地址是否传递,如果没有传递就直接报错
    if (!url) {
        throw new Error('url必须传递')
    }
    // 新建请求对象
    let xhr = new XMLHttpRequest()
    // 设置请求方式和地址
    xhr.open('post', url)
    // 设置请求头
    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    // 数据拼接
    let paramsStr = ''
    for (let key in params) {
        paramsStr += `&${key}=${params[key]}`
    }
    paramsStr = paramsStr.substring(1)
    // 发送数据
    xhr.send(paramsStr)
    // 监听状态变化
    xhr.onreadystatechange = () => {
        // 成功就调用回调函数传递参数出去
        if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
            callback(JSON.parse(xhr.responseText))
        }
    }
}
复制代码

ajax封装

复制代码
// 封装get和post方法
export const ajax = (url, option, callback) => {
    //判断是否有传入url,没传直接报错
    if (!url) {
        throw new Error()
    }
    //设置一个默认的参数对象(url内的)
    let defalutOption = {
        method: 'get',
        data: {},
        contentType: 'application/json',
        timeout: 3000
    }
    //遍历对象里的key
    for (let key in option) {
        //如果默认参数对象里有就用option里的key来替换掉
        if (defalutOption[key]) {
            defalutOption[key] = option[key]
        }
    }
    //新建请求对象
    let xhr = new XMLHttpRequest()
    //如果是get请求
    if (defalutOption.method == 'get') {
        //就先遍历对象再判断url内是否存在'?'
        for (let key in option) {
            if (!url.includes('?')) {
                url += `??{key}=${option[key]}`
            } else {
                url += `&${key}=${option[key]}`
            }
        }
    }
    //设置请求方式和请求地址
    xhr.open(defalutOption.method, url)
    //设置请求头
    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    //如果是post请求
    if (defalutOption.method == 'post') {
        //数据拼接发送
        let optionStr = ''
        for (let key in defaultOption.data) {
            optionStr += `&${key}=${defaultOption.data[key]}`
        }
        //删除最前面的&
        optionStr = optionStr.substring(1)
        //发送请求
        xhr.send(optionStr)
    } else {
        xhr.send()
    }
    //监听状态变化
    xhr.onreadystatechange = () => {
        if (xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)) {
            callback(JSON.parse(xhr.responseText))
        }
    }
}
复制代码

ajax promise封装

复制代码
//抽取post请求和get请求
export const ajax = (url, option) => {
    //判断是否具备url
    if (!url) {
        throw new Error()
    }
    //你传什么就改什么 不传为默认值
    let defalutOption = {
        method: 'get',
        data: {},
        contentType: 'application/json',
        timeout: 3000
    }
    //遍历对象里面key
    for (let key in option) {
        //默认的选项里面存在这个key
        if (defalutOption[key]) {
            //用option里面对应key的值来替换默认值
            defalutOption[key] = option[key]
        }
    }
    //新建请求对象
    let xhr = new XMLHttpRequest()
    //判断是get请求还是post请求
    if (defalutOption.method == 'get') {
        //遍历对象中所有的属性
        for (let key in defaultOption.data) {
            //判断url里面是否存在? 如果没有就加上
            if (!url.includes('?')) {
                url += `?${key}=${defaultOption.data[key]}`
            } else {
                url += `&${key}=${defaultOption.data[key]}`
            }
        }
    }
    xhr.open(defalutOption.method, url)
    //设置请求头
    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    //判断是否为post请求
    if (defalutOption.method == 'post') {
        //数据拼接发送
        let paramsStr = ''
        for (let key in defalutOption.data) {
            paramsStr = defalutOption.data[key]
        }
        //删除最前面的&
        paramsStr = paramsStr.substring(1)
        //发送请求
        xhr.send(paramsStr)
    } else {
        //发送请求
        xhr.send()
    }
    return new Promise((resolve, reject) => {
        //监听请求状态改变
        xhr.onreadystatechange = () => {
            //判断是否成功
            if (xhr.readyState == 4) {
                //成功调用resolve传递数据
                //先转为对象再传递出去
                if (/^2\d{2}$/.test(xhr.status)) {
                    resolve(JSON.parse(xhr.responseText))
                }
                if (/^4\d{2}$/.test(xhr.status)) {
                    reject()
                }
            }
        }
        //如果xhr对象有错也调用reject
        xhr.onerror = () => {
            reject()
        }
    })
}
复制代码

 

posted @   邱你咋滴  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示