探索同步异步,Ajax,回调函数,Promise

目录

一.Ajax简介

1.异步与同步的概念

2.为什么说同步请求会"重新加载整个页面",而异步"只会加载部分页面",这是什么意思?

3.Ajax的功能及优势

功能

优势

4.Ajax为什么叫异步的javascript和xml        

二.Ajax操作流程

请求

响应

三.快速入门

解读

XMLHttpRequest对象的功能

四.Axios异步库

解读

1.回调函数

2.回调地狱

3.Promise

(1)Promise 对象有以下两个特点:

(2)Promise 对象的返回值

(3)Promise 对象的异步执行后的调用方法


一.Ajax简介

   AJAX(Asynchronous JavaScript And XML) :异步的 JavaScript 和 XML

1.异步与同步的概念

同步在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其他的命令。

        服务器一接收客户端请求,马上响应,这样客户端可以在最短的时间内得到结果,但是如果多个客户端,或者一个客户端发出的请求很频繁,服务器无法同步处理,就会造成涌塞

异步执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。

        在异步请求中,当服务器接收到请求后,并不会立即处理,而是将请求放入任务队列(或称为消息队列)中等待处理。这种放入队列中的操作并不是直接处理请求,而是将请求排队等待服务器资源和处理能力。等服务器空闲了,会通过事件循环或其他机制从队列中取出请求,进行实际的处理。异步请求的处理是延后的、非阻塞的

⭐底层怎么理解呢?

类似多线程中,多个线程同时运行去争夺cpu资源,而这里与多线程不一样的是有一个优先级的

同步请求>异步请求

只要有发起同步请求就绝对不会去执行异步请求,cpu不会向异步发放线程资源,而同步只会去使用主线程,所以多个同步请求会在同一个线程中去按照顺序去执行,是按照请求顺序不是多个同步请求并发争夺资源,只是单纯的单线程执行。

而如果有多个异步请求同时发布呢,cpu就会给每一个请求分发线程资源包含主线程,真正的并行处理,当cpu资源不足时,会出现并发争夺线程资源的情况。

2.为什么说同步请求会"重新加载整个页面",而异步"只会加载部分页面",这是什么意思?

其实,当在浏览器你打开了一个页面,该页面是在后台不断进行渲染加载的,与上方说的优先级一样

同步请求>渲染

只要有发起同步请求就不会去执行渲染(不给渲染操作发放线程资源),所以在此情况下渲染停止,所以你才会感到“加载”的感觉,当同步请求过程结束时会继续开始渲染,此时有了新的响应资源,展示出不一样的页面,而异步呢就不会使渲染停止相当于他们都是“平级”的,一般情况下异步请求不会去争夺渲染线程的资源,等异步请求结束返回了新的响应资源,展示出了不一样的页面。

这时候你可能会问:那这样不就是其实不是同步请求会重新加载,而是会重新渲染页面导致页面的重新加载吗?可是异步请求不也一直在渲染吗?那为什么会说异步不能重新加载整个页面呢?

其实这些说法都是把渲染重新加载页面两个概念搞混了,渲染和重新加载页面是两个不同的概念,渲染页面是一个持续的过程,从页面的初始化加载到用户与页面进行交互,期间可能会进行局部刷新、异步请求等操作,但整个页面并不会被完全重新加载。而重新加载页面则是将整个页面的内容都重新加载一遍,包括重新获取资源、重新解析 HTML、重新计算样式、重新布局元素,并进行重新绘制,一般情况下不会重新加载。所以也就是说这种情况下同步请求和异步请求其实都不是重新加载页面而是重新渲染!

其实要重新加载页面同步请求和异步请求都能通过JavaScript更新url去跳转到其他网页去重新加载页面或者使用JavaScript中的重新加载页面的方法去加载本网页,所以说不管是同步请求还是异步请求都能通过JavaScript去加载部分或整个页面,因为异步能够并行执行所以常用来更新部分页面,用户体验也好。如果都是同步请求,就好比我打cf,要么只能不动打枪,要么只能动不打枪,跟个人机一样。

3.Ajax的功能及优势

功能

1.发起异步请求:经常应用于在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页的技术,如:搜索联想、用户名是否可用校验,等等...

2.接收响应数据,并通过JavaScript代码去更新HTML

优势
  1. 不需要插件的⽀持,原⽣ js 就可以使⽤
  2. ⽤户体验好(不需要刷新⻚⾯就可以更新数据
  3. 减轻服务端的负担
  4. 缺点:搜索引擎的支持度不够,因为数据都不在页面上,搜索引擎搜索不到

4.Ajax为什么叫异步的javascript和xml        

        AJAX 主要提供了一种异步通信的机制(就是发起异步请求和传输数据的功能),而怎么样去处理数据则是由 JavaScript 完成的。而 XML 则是常用的数据格式,用于传输和交换数据。不过,现在更常用的是使用 JSON(JavaScript Object Notation)作为数据的交换格式,因为 JSON 更加轻量级、易于处理。

        所以Ajax为什么叫异步的javascript和xml,Ajax不过是发起异步请求和传输数据,数据处理依然是javascript,传输数据类型是json或xml,这个定义意思不是说Ajax代替了javascript和xml的功能,不过请求方式改成异步了吗?

        这样理解是不正确的

        AJAX 并不是实现了“异步的 JavaScript 和 XML”的意思,而是一种利用 JavaScript 和 XML 或其他格式实现整个异步通信过程的技术,我称Ajax为异步通信工具,其中数据的处理和操作逻辑由 JavaScript 负责,而数据传输格式可以是 XML、JSON 或其他格式。

二.Ajax操作流程

请求

1.前端将用户提交的数据以 JSON 格式通过Ajax发送异步请求发送到后台

        在前端脚本中获取用户输入的数据,然后使用 JavaScript 将该数据转换为 JSON 格式。接着,将 JSON 串作为参数通过Ajax发送异步请求到后端,后台的 Java 脚本可以通过 HttpServletRequest 对象获取字符串参数。

2.后端接收到前端提交的数据后,通过 JDBC 将数据插入到数据库中

        Java 后端接收到前端发送的 JSON 串后,使用 Java 内置的 JSON 库将 JSON 串转换为 Java 对象,然后使用 JDBC 连接到数据库,并将数据插入到数据库中。

响应

1.后端通过 JDBC 连接数据库,并取出需要的数据

        使用 Java 写后端脚本,通过 JDBC(Java 数据库连接)方式连接数据库,并读取需要的数据,将数据添加到 Java 数据结构中。

2.将取出的数据转换为 JSON 格式并返回给前端

        后端使用 Java 内置的 JSON 库(比如 Jackson、GSON 等)将数据转换为 JSON 格式,然后将 JSON 字符串通过 HttpServletResponse 对象返回给前端。

3.前端使用 AJAX 获取后台返回的 JSON 数据,并解析数据渲染到 HTML

        前端使用 AJAX 技术向后台发起异步请求,并从后台获取 JSON 格式的数据。前端可以使用原生 JavaScript 或第三方库(比如 jQuery 等)来进行 AJAX 请求和数据解析。在解析后的数据中,前端可以使用 HTML 标签生成页面元素。

三.快速入门

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    //1. 创建核心对象
    var xhttp;
    if (window.XMLHttpRequest) {
        xhttp = new XMLHttpRequest();
    } else {
        // code for IE6, IE5
        xhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }

    //2. 发送请求
    xhttp.open("GET", "http://localhost/Ajax_Demo/ajax_test1");
    xhttp.send();

    //3. 获取响应
    xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            alert(this.responseText);
        }
    };

</script>
</body>
</html>

解读

1.创建核心对象

        首先,通过 if (window.XMLHttpRequest) 来判断当前浏览器是否支持 XMLHttpRequest 对象。这是一种用于发送 HTTP 请求的内置对象,它提供了与服务器进行通信的功能。如果当前浏览器支持标准的 XMLHttpRequest 对象,那么将通过 new XMLHttpRequest() 创建一个新的 XMLHttpRequest 实例并将其赋值给变量 xhttp

2.发送请求

        然后,使用 xhttp.open() 方法来打开与服务器的连接,指定 GET 请求方式和请求的 URL:

xhttp.open("GET", "http://localhost/Ajax_Demo/ajax_test1");

        这里使用 GET 请求方式,请求的 URL 是 http://localhost/Ajax_Demo/ajax_test1

        接下来,调用 xhttp.send() 方法来发送异步请求到服务器:

xhttp.send();

3.获取响应

        通过xhttp监听 onreadystatechange 事件,对应的返回状态进行操作,readyState 属性表示当前 XMLHttpRequest 对象的状态,包括以下几种可能的取值:

  • 0:请求未初始化,XMLHttpRequest 对象已被创建,但未调用 open() 方法。
  • 1:服务器连接已建立,open() 方法已被调用。
  • 2:请求已接收,send() 方法已被调用,并且已接收到请求头信息。
  • 3:请求处理中,正在接收服务器的响应数据。
  • 4:请求已完成,且响应已就绪,可以获取到完整的服务器响应。

        当 readyState 和status的值发生变化时,onreadystatechange 事件会被触发,从而可以对响应状态进行处理。当 XMLHttpRequest 对象的状态变为 4 时,即请求完成时,会执行回调函数。在回调函数中,我们可以根据 status 属性的值来确定请求的结果,status 为 200 表示请求成功,可以通过 responseText 或 responseXML 属性来获取服务器的响应数据。

XMLHttpRequest对象的功能

  1. 发送异步的 HTTP 请求: 可以使用 XMLHttpRequest 对象发送各种类型的 HTTP 请求,如 GET、POST、PUT、DELETE 等。可以设置请求的 URL、请求头、请求体等。

  2. 接收服务器响应: 通过 XMLHttpRequest 对象,可以监听服务器的响应,并获取响应的状态码、响应头、响应体等信息。

  3. 获取响应数据并处理数据: 可以使用 XMLHttpRequest 对象对服务器返回的数据进行处理,比如将响应的数据显示到页面、解析 JSON 数据、上传文件等。

其实除此之外还有别的功能

  1. 使用同步请求:默认情况下,XMLHttpRequest 对象发送的是异步请求。但是,也可以通过将 async 参数设置为 false
  2. 发送 FormData 数据XMLHttpRequest 对象可以发送 FormData 对象,用于处理带有文件上传的表单数据。
  3. 监听进度:可以通过 onprogress 事件来监听上传和下载的进度。
  4. 设置请求头信息:可以通过 setRequestHeader() 方法来设置请求的头部信息,比如设置请求的 Content-Type。

四.Axios异步库

Axios(axios.js): 是一个基于 Promise 的、用于发送 HTTP 请求的 JavaScript 库,目的之一就是简化Ajax代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--引入axios的js文件-->
<script src="js/axios-0.18.0.js"></script>
<script>
    //1.get请求方式
    axios({
        method:"get",
        url:"http://localhost/Ajax_Demo/ajax_test3?username=zhangsan"
    }).then(function (resp){
        alert(resp.data);
    })

    //2.post请求方式
    axios({
        method:"post",
        url:"http://localhost/Ajax_Demo/ajax_test3",
        data:"username=zhangsan"
    }).then(function (resp){
        alert(resp.data);
    })

    //1.get简化
    axios.get("http://localhost/Ajax_Demo/ajax_test3?username=zhangsan").then(function (resp){
        alert(resp.data);
    })
    //2.post简化
    axios.post("http://localhost/Ajax_Demo/ajax_test3","username=zhangsan").then(function (resp){
        alert(resp.data);
    })

</script>
</body>
</html>

解读

        在代码块中,使用了 GET和post 请求方式,只是data所在的位置不同,get是在url后面,而post则在data中。axios 函数被调用,并传入一个配置对象,其中 method 属性被设置为``get``或``post``,url 属性被设置为请求的 URL。然后,一个 Promise 对象被返回,并且注册了一个回调函数来处理请求的响应。在回调中,resp.data 表示从服务器返回的数据,通过调用 alert 方法将其显示在弹窗中。

前面都看懂了,后面Promise对象是什么啊,回调函数又是什么???

1.回调函数

一个函数以另外一个函数为参数这个,被调用的函数被称为回调函数

至于应用的话,在排序时所用的比较器方法,lamdba表达式,回调函数是 JavaScript 中用来处理异步操作的一种常见方式,可以帮助我们在异步操作执行完毕后得到反馈或者处理异步操作的结果

function makeAjaxRequest(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4) { // 请求完成
      if (xhr.status === 200) { // 成功接收响应
        // 调用回调函数,传递返回的数据
        callback(null, xhr.responseText);
      } else {
        // 未成功接收响应,调用回调函数,传递错误信息
        callback(new Error('Request failed'));
      }
    }
  };
  xhr.open('GET', url, true);
  xhr.send();
}

function handleResponse(error, response) {
  if (error) {
    console.error('请求失败:', error);
  } else {
    console.log('请求成功,返回数据:', response);
  }
}

// 发起 Ajax 请求,并传递回调函数
makeAjaxRequest('https://api.example.com/data', handleResponse);

        来看这个Ajax的异步请求,在发起异步请求的Ajax代码外又嵌套了一层makeAjaxRequest函数,第一个参数是发起请求的url,第二个参数是回调函数名,xhr.onreadystatechange 被赋值为一个匿名函数,这个匿名函数会在 readyState 属性发生变化时被调用。这个函数通过检查 readyState 和 status 属性,来处理请求的返回结果,当readyState和status变化时函数被自动调用,再进一步调用回调函数去对响应数据执行handleResponse操作。

所以,回调函数的主要作用就是确保在异步操作完成后能够执行特定的代码逻辑,从而更清晰地管理异步操作的响应代码

2.回调地狱

当一个请求依赖上一步请求结果的时候,进行不断的嵌套,非常杂乱,不易维护,给程序员带来了很大的心理阴影,所以被叫做回调地狱

getUserInfo(function(userInfo) {
  getOrders(userInfo.id, function(orders) {
    getOrderDetails(orders[0].id, function(orderDetails) {
      processOrder(orderDetails, function(processedOrder) {
        saveOrder(processedOrder, function(savedOrder) {
          console.log("Order saved:", savedOrder);
        });
      });
    });
  });
});

回调地狱的特征

代码逻辑变得深层嵌套,增加了理解和阅读的难度。这种情况下,代码可读性和可维护性都会变差,并且调试和错误处理也会变得更加困难。

3.Promise

解决异步程序回调地狱的一种解决方式,比传统的解决方案——回调函数和事件——更合理和更强大,它是一个ECMAScript 6 提供的,目的是更加优雅地书写复杂的异步任务

emmmm,ECMAScript 6是什么?

        ECMAScript 也是一门脚本语言,缩写为ES,通常看做JavaScript的标准化规范ECMAScript6.0是JavaScript语言的下一代标准,它的目标是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。但实际上JavaScript是ECMAScript的扩展语言,因为ECMAScript只提供了最基本的语法,通俗点说只是约定了我们的代码如何编写,比如定义变量和函数,循环和分支…它只是停留在语言层面,并不能用来完成我们应用中的实际功能开发。

在浏览器环境中,JavaScript = ECMAScript + BOM + DOM

嗯,懂了,下面就开始介绍Promise对象

(1)Promise 对象有以下两个特点:

1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:

  • pending: 初始状态,不是成功或失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

(2)Promise 对象的返回值

var promise = new Promise(function(resolve, reject) {
    // 异步处理
    // 处理结束后、调用resolve 或 reject
});

当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)

(3)Promise 对象的异步执行后的调用方法

promise.then(function(data)){

}.catch(function(data)){

});

//执行成功时把返回的响应数据放在了data,

对于上方回调地狱的改善

getUserInfo()
  .then(function(userInfo) {
    return getOrders(userInfo.id);
  })
  .then(function(orders) {
    return getOrderDetails(orders[0].id);
  })
  .then(function(orderDetails) {
    return processOrder(orderDetails);
  })
  .then(function(processedOrder) {
    return saveOrder(processedOrder);
  })
  .then(function(savedOrder) {
    console.log("Order saved:", savedOrder);
  })
  .catch(function(error) {
    console.error(error);
  });

所以总的来说,axios 是基于 Promise 的 HTTP 客户端,用于发送异步 HTTP 请求。它返回的确实是一个 Promise 对象,该 Promise 对象会在请求成功或失败时被 resolve 或 reject。

在你的代码中,使用了 .then() 方法来处理请求成功时的回调函数,回调函数接收一个参数 resp,该参数包含了请求的响应数据。通过 resp.data 可以访问到响应数据,你将其以弹窗的方式展示给用户。

因为 .then() 返回的仍然是一个 Promise 对象,所以可以继续链式调用其他的 Promise 方法来处理异步操作。你还可以使用 .catch() 方法来处理请求失败时的回调函数,以及其他的处理逻辑。

这个Axios库类就是这样简化Ajax代码。

  • 33
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值