异步交互技术Ajax-Axios

news2024/9/21 16:37:48

目录

一、同步交互和异步交互

二、Ajax 

1.概述

2.如何实现ajax请求

三、异步传输数据乱码的问题

regist.html页面代码

 服务端代码处理

四、Axios

1. Axios的基本使用

(1)引入Axios文件

(2)使用Axios发送请求,并获取响应结果。

2.案例

3.请求方法的别名(推荐用这个,简单)


一、同步交互和异步交互

同步交互:在同步交互中,参与的各方在同一时间进行交流。请求一项操作后,发起方必须等待响应才能继续进行下一步操作

异步交互:在异步交互中,参与的各方可以在不同的时间进行交流。发起方发送请求后,可以继续进行其他操作,而不必等待响应。

二、Ajax 

1.概述

Ajax是如何实现异步交互的?

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。

  • AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

  • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

  • AJAX 不需要任何浏览器插件,但需要用户允许 JavaScript 在浏览器上执行。

  • XMLHttpRequest 只是实现 Ajax 的一种方式。

简单来说,我们之前发的请求通过类似 form表单标签,a标签 这种方式,现在通过 运行js代码动态决定什么时候发送什么样的请求

通过运行JS代码发送的请求浏览器可以不用跳转页面 ,我们可以在JS代码中决定是否要跳转页面

通过运行JS代码发送的请求,接收到返回结果后,我们可以将结果通过dom编程渲染到页面的某些元素上,实现局部更新

2.如何实现ajax请求

 原生javascript方式进行ajax(了解):

<script>
  function loadXMLDoc(){
      // 创建XMLHttpRequest对象
    var request=new XMLHttpRequest();
      // 设置回调函数处理响应结果
      // request.readyState  1 2 3 4(只需要知道4表示收到服务器的响应)
      // request.status		响应状态码响应行状态码
    request.onreadystatechange=function(){
      if (request.readyState==4 && request.status==200)
      {
        document.getElementById("myDiv").innerHTML=request.responseText;
      }
    }
      // 设置请求方式和请求的资源路径
    request.open("GET","/try/ajax/ajax_info.txt",true);
      // 发送请求
    request.send();
  }
</script> 

三、异步传输数据乱码的问题

由于Ajax由原生js接收响应数据解码的问题,可能会出现乱码的现象,一般标准的规定是将传输的数据用JSON数据串传输。 

比如下面的场景,一个注册页面,姓名的验证问题

前端页面要将后端响应的数据(JSON串)转发为JSON对象

后端要将数据存到一个对象,将对象转发为JSON串响应回去

regist.html页面代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>

        .ht{
            text-align: center;
            color: cadetblue;
            font-family: 幼圆;
        }
        .tab{
            width: 500px;
            border: 5px solid cadetblue;
            margin: 0px auto;
            border-radius: 5px;
            font-family: 幼圆;
        }
        .ltr td{
            border: 1px solid  powderblue;

        }
        .ipt{
            border: 0px;
            width: 50%;

        }
        .btn1{
            border: 2px solid powderblue;
            border-radius: 4px;
            width:60px;
            background-color: antiquewhite;

        }

        .msg {
            color: gold;
        }

        .buttonContainer{
            text-align: center;
        }
    </style>

    <script>

        // 校验用户名的方法
        function checkUsername(){
            // 定义正则
            var usernameReg=/^[a-zA-Z0-9]{5,10}$/
            var username =document.getElementById("usernameInput").value
            var usernameMsgSpan =document.getElementById("usernameMsg")
            if(!usernameReg.test(username)){
                usernameMsgSpan.innerText="不合法"
                return false
            }
            // 发送ajax请求校验用户名是否被占用
            var request;
            if(window.XMLHttpRequest){
                request= new XMLHttpRequest();
            }else{
                request= new ActiveXObject("Microsoft.XMLHTTP");
            }
            request.onreadystatechange= function (){
                // request.readyState == 4 代表请求结束,已经接收到响应结果
                // request.status== 200  表示后端响应状态码是200
                if(request.readyState == 4  && request.status== 200){
                    // 后端的响应的JSON字符串转换为前端的对象
                    var response =JSON.parse(request.responseText)
                    console.log(response)
                    //  判断业务码是否是200
                    if (response.code != 200){
                        usernameMsgSpan.innerText="已占用"
                        return false
                    }
                }
            }
            // 设置请求方式,请求资源路径,是否为异步请求
            request.open("GET",'/user/checkUsernameUsed?username='+username,true)
            // 发送请求
            request.send();
            // 前面校验都通过
            // usernameMsgSpan.innerText="OK"
            // return true

        }


        // 校验密码的方法
        function checkUserPwd(){
            // 定义正则
            var passwordReg=/^[0-9]{6}$/
            var userPwd =document.getElementById("userPwdInput").value
            var userPwdMsgSpan =document.getElementById("userPwdMsg")
            if(!passwordReg.test(userPwd)){
                userPwdMsgSpan.innerText="不合法"
                return false
            }
            userPwdMsgSpan.innerText="OK"
            return true
        }

        // 校验密码的方法
        function checkReUserPwd(){
            // 定义正则
            var passwordReg=/^[0-9]{6}$/
            var userPwd =document.getElementById("userPwdInput").value
            var reUserPwd =document.getElementById("reUserPwdInput").value
            var reUserPwdMsgSpan =document.getElementById("reUserPwdMsg")
            if(!passwordReg.test(userPwd)){
                reUserPwdMsgSpan.innerText="不合法"
                return false
            }
            if(userPwd != reUserPwd){
                reUserPwdMsgSpan.innerText="不一致"
                return false

            }
            reUserPwdMsgSpan.innerText="OK"
            return true
        }

        //表单提交时统一校验
        function checkForm(){
            return checkUsername() && checkUserPwd() && checkReUserPwd()
        }



    </script>
</head>
<body>
<h1 class="ht">欢迎使用日程管理系统</h1>
<h3 class="ht">请注册</h3>
<form method="post" action="/user/regist" onsubmit="return checkForm()">
    <table class="tab" cellspacing="0px">
        <tr class="ltr">
            <td>请输入账号</td>
            <td>
                <input class="ipt" id="usernameInput" type="text" name="username" onblur="checkUsername()">
                <span id="usernameMsg" class="msg"></span>
            </td>
        </tr>
        <tr class="ltr">
            <td>请输入密码</td>
            <td>
                <input class="ipt" id="userPwdInput" type="password" name="userPwd" onblur="checkUserPwd()">
                <span id="userPwdMsg" class="msg"></span>
            </td>
        </tr>
        <tr class="ltr">
            <td>确认密码</td>
            <td>
                <input class="ipt" id="reUserPwdInput" type="password" onblur="checkReUserPwd()">
                <span id="reUserPwdMsg" class="msg"></span>
            </td>
        </tr>
        <tr class="ltr">
            <td colspan="2" class="buttonContainer">
                <input class="btn1" type="submit" value="注册">
                <input class="btn1" type="reset" value="重置">
                <button class="btn1"><a  href="/login.html">去登录</a></button>
            </td>
        </tr>
    </table>
</form>
</body>
</html>

 服务端代码处理

添加公共的JSON数据响应格式类

package com.atguigu.schedule.common;

/**
 * 业务含义和状态码对应关系的枚举
 *
 */
public enum ResultCodeEnum {

    SUCCESS(200,"success"),
    USERNAME_ERROR(501,"usernameError"),
    PASSWORD_ERROR(503,"passwordError"),
    NOTLOGIN(504,"notLogin"),
    USERNAME_USED(505,"userNameUsed")
    ;

    private Integer code;
    private String message;
    private ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
    public Integer getCode() {
        return code;
    }
    public String getMessage() {
        return message;
    }
}

package com.atguigu.schedule.common;


/**
 * 全局统一响应的JSON格式处理类
 *
 */
public class Result<T> {
    // 返回码
    private Integer code;
    // 返回消息
    private String message;
    // 返回数据
    private T data;
    public Result(){}
    // 返回数据
    protected static <T> Result<T> build(T data) {
        Result<T> result = new Result<T>();
        if (data != null)
            result.setData(data);
        return result;
    }
    public static <T> Result<T> build(T body, Integer code, String message) {
        Result<T> result = build(body);
        result.setCode(code);
        result.setMessage(message);
        return result;
    }
    public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
        Result<T> result = build(body);
        result.setCode(resultCodeEnum.getCode());
        result.setMessage(resultCodeEnum.getMessage());
        return result;
    }
    /**
     * 操作成功
     * @param data  baseCategory1List
     * @param <T>
     * @return
     */
    public static<T> Result<T> ok(T data){
        Result<T> result = build(data);
        return build(data, ResultCodeEnum.SUCCESS);
    }
    public Result<T> message(String msg){
        this.setMessage(msg);
        return this;
    }
    public Result<T> code(Integer code){
        this.setCode(code);
        return this;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}

增加Jackson依赖

添加WEBUtil工具类  (后面SpringMVC框架会提供方法)

package com.atguigu.schedule.util;


import com.atguigu.schedule.common.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.SimpleDateFormat;

public class WebUtil {
    private static ObjectMapper objectMapper;
    // 初始化objectMapper
    static{
        objectMapper=new ObjectMapper();
        // 设置JSON和Object转换时的时间日期格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }
    // 从请求中获取JSON串并转换为Object
    public static <T> T readJson(HttpServletRequest request,Class<T> clazz){
        T t =null;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            StringBuffer buffer =new StringBuffer();
            String line =null;
            while((line = reader.readLine())!= null){
                buffer.append(line);
            }

            t= objectMapper.readValue(buffer.toString(),clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return t;
    }
    // 将Result对象转换成JSON串并放入响应对象
    public static void writeJson(HttpServletResponse response, Result result){
        response.setContentType("application/json;charset=UTF-8");
        try {
            String json = objectMapper.writeValueAsString(result);
            response.getWriter().write(json);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

用户名校验业务接口代码  

  /** 
     * SysUserController下,注册时校验用户名是否被占用的业务接口
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void checkUsernameUsed(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        SysUser registUser = userService.findByUsername(username);

        //封装结果对象
        Result result=null;
        if(null ==registUser){
            // 未占用,创建一个code为200的对象
            result= Result.ok(null);
        }else{
            // 占用, 创建一个结果为505的对象
            result= Result.build(null, ResultCodeEnum.USERNAME_USED);

        }
        // 将result对象转换成JSON并响应给客户端
        WebUtil.writeJson(resp,result);

    }

四、Axios

上述原生的Ajax请求的代码编写起来还是比较繁琐的,所以接下来我们学习一门更加简单的发送Ajax请求的技术Axios 。Axios是对原生的AJAX进行封装,简化书写。Axios官网是:https://www.axios-http.cn

1. Axios的基本使用

(1)引入Axios文件

就是一个js文件,可以到官网下载。

<script src="js/axios-0.18.0.js"></script>

(2)使用Axios发送请求,并获取响应结果。

官方提供的api很多,此处给出2种,如下  

发送 get 请求

axios({
    method:"get",
    url:"http://localhost:8080/ajax-demo1/aJAXDemo1?username=zhangsan"
}).then(function (resp){
    alert(resp.data);
})

 发送 post 请求

axios({
    method:"post",
    url:"http://localhost:8080/ajax-demo1/aJAXDemo1",
    data:"username=zhangsan"
}).then(function (resp){
    alert(resp.data);
});

axios()是用来发送异步请求的,小括号中使用 js的JSON对象传递请求相关的参数:

  • method属性:用来设置请求方式的。取值为 get 或者 post。

  • url属性:用来书写请求的资源路径。如果是 get 请求,需要将请求参数拼接到路径的后面,格式为: url?参数名=参数值&参数名2=参数值2。

  • data属性:作为请求体被发送的数据。也就是说如果是 post 请求的话,数据需要作为 data 属性的值。

then() 需要传递一个匿名函数。我们将 then()中传递的匿名函数称为 回调函数,意思是该匿名函数在发送请求时不会被调用,而是在成功响应后调用的函数。而该回调函数中的 resp 参数是对响应的数据进行封装的对象,通过 resp.data 可以获取到响应的数据。

2.案例

向后端请求数据:

后端实现

查询所有员工信息服务器地址:http://yapi.smart-xwork.cn/mock/169327/emp/list

根据员工id删除员工信息服务器地址:http://yapi.smart-xwork.cn/mock/169327/emp/deleteById

 前端实现

  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Ajax-Axios</title>
      <script src="js/axios-0.18.0.js"></script>
  </head>
  <body>
      
      <input type="button" value="获取数据GET" onclick="get()">
  
      <input type="button" value="删除数据POST" onclick="post()">
  
  </body>
  <script>
      function get(){
          //通过axios发送异步请求-get
          axios({
              method: "get",
              url: "http://yapi.smart-xwork.cn/mock/169327/emp/list"
          }).then(result => {
              console.log(result.data);
          })
  
  
      }
  
      function post(){
         // 通过axios发送异步请求-post
          axios({
              method: "post",
              url: "http://yapi.smart-xwork.cn/mock/169327/emp/deleteById",
              data: "id=1"
          }).then(result => {
              console.log(result.data);
          })
  
      }
  </script>
  </html>

 浏览器F12获取,然后分别点击2个按钮,查看控制台效果如下:

3.请求方法的别名(推荐用这个,简单)

Axios还针对不同的请求,提供了别名方式的api,具体如下:

方法描述
axios.get(url [, config])发送get请求
axios.delete(url [, config])发送delete请求
axios.post(url [, data[, config]])发送post请求
axios.put(url [, data[, config]])发送put请求

在上述的案例中,我们可以将get请求代码改写成如下:

axios.get("http://yapi.smart-xwork.cn/mock/169327/emp/list").then(result => {
    console.log(result.data);
})

post请求改写成如下:

axios.post("http://yapi.smart-xwork.cn/mock/169327/emp/deleteById","id=1").then(result => {
    console.log(result.data);
})

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2057929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Chapter 42 递归

欢迎大家订阅【Python从入门到精通】专栏&#xff0c;一起探索Python的无限可能&#xff01; 文章目录 前言一、基本概述二、案例分析 前言 递归是一种在编程中广泛使用的技术&#xff0c;通过让函数调用自身来逐步解决问题。本章详细讲解了 Python 中递归的基本原理以及应用场…

SSRF服务器请求伪造

目录 SSRF服务器请求伪造 一、SSRF漏洞概述 二、SSRF常见的函数 1、file_get_contents() 2、fsockopen() 3、exec()发送GET请求 4、exec()发送POST请求 三、SSRF主要危害 1、先准备以下脚本 2、读取文件和信息 3、内网扫描 4、获取指纹信息 四、SSRF漏洞挖掘技巧 …

Nginx---Web服务器

简介 介绍nginx中Web服务器的相关配置 环境配置 mkdir /data/web/html -p mkdir /data/web/html/test{1..5} echo test1 > /data/web/html/test1/index.html echo test2 > /data/web/html/test2/index.html echo test3 > /data/web/html/test3/index.html echo tes…

FPGA时序约束

目录 一、概述二、时序分析基本概念时钟抖动时钟偏差时钟不确定性Clock Uncertainty同步电路和异步电路建立时间和保持时间发起沿和采样沿关键路径 三、时序分析的基本公式时序分析的基本路径数据到达时间和时钟到达时间建立时间的裕量&#xff08;Setup slack&#xff09;保持…

STM32CubeMX 配置串口通信 HAL库

一、STM32CubeMX 配置串口 每个外设生成独立的 ’.c/.h’ 文件 不勾&#xff1a;所有初始化代码都生成在 main.c 勾选&#xff1a;初始化代码生成在对应的外设文件。 如 GPIO 初始化代码生成在 gpio.c 中。 二、重写fputc函数 ​ #include <stdio.h>#ifdef __GNUC__#def…

“LOCAL_LISTENER”参数导致业务无法连接数据库,文末附Oracle连接故障检查监听的排查流程

1. 背景及问题 今天在Oracle BCV技术[1]做数据同步&#xff0c;建立生产库的测试库&#xff0c;需要DBA配合同步前后的停库和起库。在同步完起库后&#xff0c;有部门反应同步好的测试库连接不上去。 2. 问题排查 以我当前的知识储备&#xff0c;能想到的可能就是以下几点进…

【NLP】注意力机制:规则、作用、原理、实现方式

文章目录 1、本章目标2、注意力机制介绍2.1、注意力概念2.2、注意力机制2.3、翻译举例 3、注意力计算规则3.1、打个比喻3.2、公式3.2.1、线性变换 点积注意力3.2.2、加性注意力3.2.3、点积注意力3.2.4、对比与总结3.2.5、bmm运算 4、注意力机制的作用5、注意力机制原理⭐5.1、…

基于java的美食信息推荐系统的设计与实现论文

摘 要 使用旧方法对美食信息推荐系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在美食信息推荐系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的美…

Linux系统-vi/vim编辑器权限管理文档处理三剑客

1.vi/vim文本编辑器 vim是vi的增强版&#xff0c;vi是系统自带的。以下命令在vi/vim中通用&#xff1a; 刚打开的默认模式 快捷键&#xff1a;gg 跳到文件开头&#xff0c;G 跳到文件最后一行。 快捷键&#xff1a;0 跳到行首&#xff0c;$ 跳到行尾。 快捷键&#xff1a;…

C++ | Leetcode C++题解之第355题设计推特

题目&#xff1a; 题解&#xff1a; class Twitter {struct Node {// 哈希表存储关注人的 Idunordered_set<int> followee;// 用链表存储 tweetIdlist<int> tweet;};// getNewsFeed 检索的推文的上限以及 tweetId 的时间戳int recentMax, time;// tweetId 对应发送…

vue3--定时任务cron表达式组件比较

## 背景&#xff1a; 之前使用vue2开发项目时&#xff0c;使用了cron组件&#xff0c;比较了两种组件的使用效果。现在需要把原有的vue2项目升级为vue3&#xff0c;需要对应的cron组件。 方案一&#xff0c;vue3-cron-plus 具体实现&#xff1a; 安装插件 npm install vue3-…

浅谈shell中的while true

目录 shell实现死循环你了解while true中的true吗重新认识true和falsewhile true存在的问题实现shell死循环的另一种方法 在shell中实现死循环&#xff0c;一般都会用 while true&#xff0c;那你知道执行while true时&#xff0c;进程都在做些什么吗&#xff1f; shell实现死…

云计算实训32——安装nginx(修改端口为8080)、roles基本用法、使用剧本安装nginx、使用roles实现lnmp

一、安装nginx并更改其端口 编辑hosts配置文件 [rootmo ~]# vim /etc/ansible/hosts 创建目录 [rootmo ~]# mkdir /etc/ansible/playbook 编辑配置文件 [rootmo ~]# vim /etc/ansible/playbook/nginx.yml 执行测试 [rootmo ~]# ansible-playbook /etc/ansible/playbook/n…

【案例49】ORA-01000:超出打开游标的最大数

问题现象 在登录系统时提示报错&#xff1a;ORA-01000 超出打开游标的最大数。 问题分析 游标就是看成是指向结果集的指针。可以把它看成一种资源&#xff0c;或者一种数据结构。 ORA-01000是开发中常见的异常。这个异常表示程序中打开的游标数目> 数据库中设定的可以打开…

OpenCV几何图像变换(2)计算仿射变换矩阵的函数getAffineTransform()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算三对对应点之间的仿射变换。 该函数计算 23 的仿射变换矩阵&#xff0c;使得&#xff1a; [ x i ′ y i ′ ] map_matrix ⋅ [ x i y i 1 …

Datawhale AI 平台 证书 存个档

&#xff01;证书不怕多 &#x1f508; 大模型开发 工程师 欢迎参与 Datawhale 大模型开发 工程师 计划 联合浪潮信息 面向在校学生、社会在职人士 可获官方颁发的 大模型开发工程师 证书 认证地址&#xff1a;大模型开发工程师考试入口&#xff08;电脑端打开&#xff09;评…

C++笔记---类和对象(下)

1. 初始化列表 1.1 初始化列表的使用 在构造函数中&#xff0c;对成员变量进行初始化可以说是公式化的步骤&#xff0c;而初始化列表就将这一步骤进行了标准化。 初始化列表紧跟在构造函数的参数列表后面&#xff0c;使用方式是以一个冒号开始&#xff0c;接着是一个以逗号分…

今日总结:解决了三个小问题

问题01 1.在Bootstrap5中&#xff0c;offcanvas失去焦点后会自动回到顶端&#xff0c;用了一个非常简单的方法&#xff0c;将触发侧边栏的按钮代码由 <button type"button">换成 <a type"button">更多解决方法详见&#xff1a;更多方法 注…

杰发科技AC7801——GPIO通过寄存器地址控制高低电平

通过这个寄存器来查看控制的是哪个ODR值&#xff0c;使用sample&#xff0c;发现是0x20080068的第7和第9位 使用51控制寄存器的代码来置高置低代码&#xff0c;注意变量需要用unsigned int来声明 unsigned int ledBit 0;mdelay(100);ledBit | (1 << 9); ledBit & ~…

【第五节】Win32汇编程序设计

目录 一、汇编的第一个“helloworld” 二、汇编中的标号 三、的使用 四、数据定义 五、全局变量 六、局部变量 七、结构体 八、结构体的访问 九、获取变量地址 十、函数 十一、分支与循环 十二、内联汇编 十三、裸函数的使用 一、汇编的第一个“helloworld” .38…