day22-ajax

1.ajax 

关键词

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

  • 进程 (正在运行的程序)

  • 同步(一个线程执行 (同步阻塞))

    上一个没有做完 下一个不能执行

  • 异步 (多个线程)

    上一个和这一个没有关系

概述

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

请求流程

ajax的代码实现

//新建请求对象
var xhr = new XMLHttpRequest()
//以对应的请求方式来打开对应的请求地址
xhr.open('get', 'http://jsonplaceholder.typicode.com/todos')
//发送请求
xhr.send()
//监听请求状态的变化 readystate (1-5  1准备发送  2 发送完成 3 发送完成数据准备接收  4数据接收完毕 5 错误)
xhr.onreadystatechange = () => {
    //进行判断对应的状态 4是数据接收完毕
    if (xhr.readyState == 4) {
        //responseText 表示返回的文本(字符串)
        console.log(xhr.responseText)
    }
}

2.XMLHttpRequest对象的相关属性及方法

属性

  • readyState 状态码

  • status http状态码

  • timeout 超时时间

  • responseText 响应文本

方法

  • open 打开一个请求

  • send 发送请求

  • setRequestHeader 设置请求头

  • getResponseHeader 获取响应头

事件

  • onreadystatechange 监听状态的改变

var xhr = new XMLHttpRequest()
//属性
//readyState 对应的xhr对象的一个状态码(这个状态码只有xhr才有)
// 0 没有请求  1准备发送 2请求已经发送 3请求发送完毕 准备接收响应数据 4响应接收完毕
console.log(xhr.readyState);
//status http状态码 (只要发送http请求都会有)
// 取值为100 - 599
// 1开头(表示成功 但是需要后续操作) 
// 2开头 (成功 200) 
// 3开头 (重定向 304) 
// 4开头 (表示客户端错误 404(找不到页面) 403(权限不足))
// 5开头 (表示服务器错误 500)
console.log(xhr.status);
//responseText 响应的文本
console.log(xhr.responseText);
//responseXML 响应的xml
console.log(xhr.responseXML);
//响应类型
console.log(xhr.responseType);
//响应的地址
console.log(xhr.responseURL);
//设置请求的超时时间 
console.log(xhr.timeout );
//方法
//设置请求 open 请求方式  请求地址
xhr.open('get','')
//发送方法 里面的传递的参数是设置给请求体的内容
xhr.send('')
//请求头相关 设置请求头 通过键值对的方式  键 值 都是字符串
xhr.setRequestHeader('Connection','keep-alive')
//响应头获取 通过key来获取value
xhr.getResponseHeader('Content-type')
//事件 当前状态改变的事件
xhr.onreadystatechange = ()=>{
    //判断readyState为4 http状态码以2开头
    if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
        //接收数据进行处理
    }
}

3.数据渲染案例

<button>请求数据</button>
<ul>
</ul>
<script>
    //获取ul
    var ul = document.querySelector('ul')
    // http://jsonplaceholder.typicode.com/todos?_limit=10&_page=2
    //get请求的传参使用?和&做拼接 search传参(query传参)
    //第一个前面要添加? 对应的多个参数使用&连接
    //get传参时使用地址的拼接来传递参数
    // _limit表示 个数  _page表示页数
    document.querySelector('button').onclick = function(){
        //请求数据
        var xhr = new XMLHttpRequest()
        //设置请求地址
        xhr.open('get','http://jsonplaceholder.typicode.com/todos')
        //发送请求
        xhr.send()
        //接收响应数据
        xhr.onreadystatechange = ()=>{
            if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
                //接收数据
                var str = xhr.responseText
                //将字符串转为对应的对象
                var result = JSON.parse(str)
                //渲染
                //遍历result进行渲染
                result.forEach(item => {
                    ul.innerHTML += ` <li>
                        id: ${item.id}
                        ${item.title}
                        ${item.completed?'💘':'💔'}
                    </li>`
                });
            }
        }
    }
</script>

4.get请求封装

//封装一个对应的get请求的方法
//请求地址   参数 (以对象传递)  对应的处理不一样
export function get(url,params={},callback){
    //判断url地址是否传递 如果没有传递直接报错
    if(!url){
        throw new Error('地址必须传递')
    }
    //新建请求对象
    let xhr = new XMLHttpRequest()
    //设置请求地址 (拼接参数到url)
    //遍历对象中所有的属性
    for(let key in params){
        // {_limit:10,_page:1}
        // http://jsonplaceholder.typicode.com/todos?_limit=10&_page=1
        //判断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))
        }
    }
}

5.分页渲染示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button>1</button>
    <button>2</button>
    <button>3</button>
    <button>4</button>
    <button>5</button>
    <ul>
    </ul>
    <script type="module">
        import {get} from './ajax.js'
        //获取ul
        var ul = document.querySelector('ul')
        //获取所有按钮
        var btns = document.querySelectorAll('button')
        //遍历按钮添加事件
        Array.from(btns).forEach((v,i)=>{
            v.onclick = ()=>{
                get('http://jsonplaceholder.typicode.com/todos',{
                    _limit:10,
                    _page:i+1
                },(res)=>{
                    ul.innerHTML = ''
                    res.forEach(item => {
                        ul.innerHTML += ` <li>
                            id: ${item.id}
                            ${item.title}
                            ${item.completed?'💘':'💔'}
                        </li>`
                    });
                })
            }
        })
    
    </script>
</body>
</html>

6.简单的post请求

 <!-- action 提交的地址  method 提交的方式 -->
 <form action="https://jsonplaceholder.typicode.com/posts" method="post">
        <!-- 如果使用action进行提交 那么提交的内容在对应的输入框中 提交的时候以key value提交
        name属性表示的是key  对应的value是输入框的值 
        <input type="text" name="uname">
        <input type="password" name="upwd">     
        <button type="submit">登录</button>
    </form>
    <!-- 通过form发送的post请求 需要指定请求方式 这个请求的数据以表单形式发送的 
    没有指定请求方式 默认以get方式提交 
        数据暴露在地址栏  他是通过?和&进行拼接 (对应的get请求提交的数据通过字符串的形式)
        get请求提交的数据有限 (2kb)
        get请求因为在地址栏 所以他会有历史记录
        get请求是不安全
    只有指定为post才会以post请求提交
        post请求 数据是会封装成表单对象存储在对应的请求体中进行提交
        数据提交的容量 要远远大于get请求的
        而post请求没有历史记录
        post安全性要高于get请求
    -->
    <!-- 异步的post请求 -->
    <script>
        //获取form表单
        document.forms[0].onsubmit = ()=>{
            //获取input框的数据
            var inputs = document.querySelectorAll('input')
            var username = inputs[0].value
            var password = inputs[1].value
            //新建请求对象
            var xhr = new XMLHttpRequest()
            //打开连接
            xhr.open('post','https://jsonplaceholder.typicode.com/posts')
            //设置请求头 告诉后台的我的内容为表单形式
            //内容的类型为表单形式
            xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
            //发送数据 key=value&key=value send里面的数据放入在请求体
            xhr.send(`username=${username}&password=${password}`)
            //监听状态改变
            xhr.onreadystatechange = ()=>{
                if(xhr.readyState == 4 && /^2\d{2}$/.test(xhr.status)){
                    console.log(xhr.responseText);
                }
            }
            //禁止默认行为
            return false
        }
    </script>
post请求封装

//封装post请求
export function post(url,params={},callback){
    //判断url地址是否传递 如果没有传递直接报错
    if(!url){
        throw new Error('地址必须传递')
    }
    //新建请求对象
    let xhr = new XMLHttpRequest()
    //设置请求地址 (拼接参数到url)
    xhr.open('post',url)
    //设置请求头
    xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
    //数据拼接发送
    let paramsStr = ""
    for(let key in params){
        // {_limit:10,_page:1}
        // _limit=10&_page=1
        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))
        }
    }
}

7.ajax封装

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

8.ajax promise封装

//将post请求和get请求抽取 
export const ajax = (url,option)=>{
    //判断是否具备url
    if(!url){
        throw new Error('地址必须传递')
    }
    //你传什么就改什么 不传为默认值
    let defaultOption = {
        method:'get',
        data:{},
        contentType:'application/json',
        timeout:'3000'
    }
    //遍历对象里面key
    for(let key in option){
        //默认的选项里面存在这个key
        if(defaultOption[key]){
            //用option里面对应key的值来替换默认值
            defaultOption[key] = option[key]
        }
    }
    //新建请求对象
    let xhr = new XMLHttpRequest()
    //判断是get请求还是post请求
    if(defaultOption.method == 'get'){
        //设置请求地址 (拼接参数到url)
        //遍历对象中所有的属性
        for(let key in defaultOption.data){
            // {_limit:10,_page:1}
            // http://jsonplaceholder.typicode.com/todos?_limit=10&_page=1
            //判断url里面是否存在? 如果没有就加上
            if(!url.includes('?')){
                url+=`?${key}=${defaultOption.data[key]}`
            }else{
                url+=`&${key}=${defaultOption.data[key]}`
            }
        }
    }
    xhr.open(defaultOption.method,url)
    //设置请求头
    xhr.setRequestHeader('content-type',defaultOption.contentType)
    //判断是否为post请求
    if(defaultOption.method == 'post'){
        //数据拼接发送
        let paramsStr = ""
        for(let key in defaultOption.data){
            // {_limit:10,_page:1}
            // _limit=10&_page=1
            paramsStr += `&${key}=${defaultOption.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()
    }
   })
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值