2024年9月19日---关于ES6(2)

五 异步编程

5.1 回调函数

5.1.1 概念

回调函数(callback function),当一个函数作为参数传入另一个参数中,并且它不会立即执行,只有当满足一定条件后该函数才可以执行,这种函数就称为回调函数。 你可以将其理解为 回头再调用的意思, 其实回调函数就是普通函数,只不过名字起的特殊,根据应用场景而命名的而已。

回调函数通常用于事件处理异步编程处理各种操作系统和框架的API。

基本概念:

  1. 回调:指被传入到另一个函数的函数。

  2. 异步编程:指在代码执行时不会阻塞程序运行的方式。

  3. 事件驱动:指程序的执行是由外部事件触发而不是顺序执行的方式。

5.1.2 应用场景

回调函数是一种常见的编程技术,它可以在异步操作完成后调用一个预定义的函数来处理结果。回调函数通常用于处理事件、执行异步操作或响应用户输入等场景。

回调函数的作用是将代码逻辑分离出来,使得代码更加模块化和可维护。使用回调函数可以避免阻塞程序的运行,提高程序的性能和效率。另外,回调函数还可以实现代码的复用,因为它们可以被多个地方调用。

回调函数的使用场景包括:

  1. 事件处理:回调函数可以用于处理各种事件,例如鼠标点击、键盘输入、网络请求等。

  2. 异步操作:回调函数可以用于异步操作,例如读取文件、发送邮件、下载文件等。

  3. 数据处理:回调函数可以用于处理数据,例如对数组进行排序、过滤、映射等。

  4. 插件开发:回调函数可以用于开发插件,例如 WordPress 插件、jQuery 插件等。

回调函数是一种非常灵活和强大的编程技术,可以让我们更好地处理各种异步操作和事件。

例子1:
let nums = [10, 20, 30, 40];
let f1 = (value, index) => console.log(value, index);
nums.forEach(f1)
​
例子2:
let f1 = () => { console.log("aaaaaa"); }
document.getElementById("btn").addEventListener("click", f1)
​
例子3: 定时器里的第一个参数:就是回调函数。  3秒后回头来调用该函数 
setTimeout(()=>{console.log("hello world")
},3000)

5.2 同步和异步

5.2.1 同步编程简介

所谓==同步==:就是程序按照代码的顺序执行,一次只执行一个任务,当前任务执行完毕,才能执行下一个任务。

1)同步编程的优点:

  • 代码逻辑简单

    在同步编程中,代码的执行顺序与编写顺序一致。这意味着开发者在编写程序时,可以按照其自然逻辑去组织代码。这样的一对一映射关系大大降低了程序逻辑的复杂性,使得代码更易维护和扩展。
  • 强顺序控制

    由于执行流程是按部就班的,同步编程确保了程序的严格顺序控制。某一任务必须完成后,才会执行下一个任务。这对于某些依赖于前一操作结果的任务特别有用。
  • 易于理解和调试

    对于开发者来说,同步代码通常更容易理解。而且在调试过程中,由于操作顺序固定且有序,开发者可以更准确地预测错误发生的位置及原因。
  • 资源利用和管理

    在同步编程模式下,资源管理相对简单。开发者不需要关注资源在不同线程或进程间的共享问题,可以避免多线程程序中的锁和同步机制,减少系统开销。
  • 稳定性和一致性

    由于程序的执行是串行的,避免了多线程编程中常见的竞态条件和副作用。这使得同步程序在运行时更加稳定,输出结果也更加一致。

2)同步编程的缺点

  • 性能问题

    同步编程会阻塞程序的执行,当某个操作耗时较长时,会导致程序的整体性能下降。特别是在处理大量的并发请求时,同步编程可能造成长时间的等待,无法充分利用系统资源。
  • 处理并发问题的能力有限

    由于同步编程是按照代码的执行顺序依次执行,无法在多个线程之间进行快速切换。因此,同步编程在处理大量的并发请求时可能无法很好地发挥其优势,导致性能瓶颈
  • 代码复杂度增加

    在同步编程中,由于每个操作都需要等待前一个操作完成,可能导致代码的嵌套层级较深,逻辑复杂。特别是在处理多个依赖性较强的操作时,代码的可读性和可维护性会受到一定的影响。

5.2.2 JavaScript的同步演示

JavaScript编程语言,默认是单线程机制,也就是同步。我们来演示一个同步案例: 注册页面的填写和验证功能

1、准备一个注册页面

2、给用户名添加失去焦点事件

3、绑定事件处理函数,先验证正则表达式,然后验证用户名是否已经被占用

4、用户名提交到服务端,然后使用伪代码来模拟验证时间花了30秒左右

案例总结:

当校验用户名是否已经被占用时,我们会向服务端发送一个请求操作。服务器在收到请求后,一定会出现下面三种状态中某一种。
1. 验证成功:success
2. 验证失败:fail
3. 验证中:  pending   还没有得到具体的结果(成功,失败)
​
假设页面是同步行为,那么验证失败或者成功的这个时间段非常短,在一秒以内,那么对于用户的体验感是没有多大影响的,
如果因为网络波动或者其他原因,服务器要经过5秒甚至30秒以上的时间才给浏览器反馈,那么用户也得等待5秒甚至30秒以上的时间后,才能填写后续的文本框内容。这样的用户体验特别不好!
​
什么叫好的用户体验?当验证用户名时,用户依然可以往下填写内容。这样的体验较好。 用户行为和校验请求是异步的(同时进行的)。

还有一个问题待解决,就是页面总刷新的问题。

在登录页面中,我们使用转发技术做用户名或者密码校验时,会涉及到一个页面重新刷新的动作。 因为服务器会将整个页面资源进行打包响应给浏览器,浏览器会重新加载整个完整的页面。 如果页面资源比较多,那么一定会占用过多的网络传输IO。
​
代码如下:
RequestDispatcher  rd =  request.getRequestDispatcher("login.jsp")
rd.forward(request,response)

JSP页面:index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>$Title$</title><style>#wrap{width: 600px;margin: 0 auto;}#wrap legend{text-align: center;}#wrap input{margin-block: 10px;}</style></head><body><form action="regist.lr" method="post" οnsubmit="return regist()"><fieldset id="wrap"><legend>注册页面</legend>用户名:   <br><input type="text" οnblur="checkUsername()" id="username" placeholder="请注册用户名"> <span id="msg_uname"></span> <br>密码:<br><input type="text" id="password" placeholder="请输入密码"> <br>手机:<br><input type="text" id="repassword" placeholder="请输入手机号"> <br>性别:<input type="radio" name="gender" value="f" checked> 女<input type="radio" name="gender" value="m"> 男  <br><button type="submit">注册</button></fieldset></form></body><script>function  checkUsername(){let username = $("username").value;let regex = /^[\w]{8,12}$/if(!regex.test(username)){alert("不符合正则表达式");return false;}let xhr = getXhr();xhr.open("get","http://localhost:8088/jsp_day03/checkUsername.lr?username="+username,false);xhr.onreadystatechange=function () {if(xhr.readyState==4&&xhr.status==200){$("msg_uname").innerText = xhr.responseText;}}xhr.send(null)return false;}function $(id){return document.getElementById(id);}function getXhr(){let xhr = null;if(window.XMLHttpRequest){xhr = new XMLHttpRequest();}else{xhr = new ActiveXObject("Microsoft.XMLHttp");}return xhr;}</script>
</html>
​

服务端代码:MyServlet.java

package com.ajax;
​
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
​
@WebServlet("*.lr")
public class MyServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf-8");String username = req.getParameter("username");PrintWriter pw = resp.getWriter();System.out.println(username);try {Thread.sleep(30000);} catch (InterruptedException e) {throw new RuntimeException(e);}
​if("zhangsan".equals(username)){pw.println("用户名已经存在,请重新输入");}else{pw.println("用户名可以使用");}}
}
​

5.2.3 异步编程简介

在传统的同步编程中,任务一般会逐一执行,导致后续任务必须等待前一个任务完成后才能开始。与之相对,异步编程允许程序在等待某些操作(如数据的读写或网络请求)完成时继续执行其他任务,从而有效减少等待时间和提高程序运行效率。

==异步==的任务,并不会像同步任务一样按照顺序执行,而是当一个异步任务被创建以后,他会被放入==任务队列==中进行等待,然后通过一定的机制,来让其回到主线程继续执行。

console.log("任务1--同步");
console.log("任务2--同步");
setTimeout(function () { console.log("任务3--异步"); }, 0)
console.log("任务4--同步");

异步编程的两大核心优势

  • 提升执行效率

    异步编程通过并行处理多个操作或任务,有效地利用系统资源,尤其是在涉及到I/O操作(如文件读写、网络请求等)的场景中,能显著减少程序的闲置时间,从而加速程序的整体运行速度。

  • 改善用户体验

尽管异步编程带来了诸多好处,但它也引入了一些挑战,主要包括代码复杂性增加和调试难度提升。由于异步代码的执行顺序不像同步代码那样直观,因此维护和理解异步代码可能会更加困难。

==不过,异步编程的优点远远大于缺点的。==

异步编程的两个关键概念

  • 事件循环

    事件循环是异步编程的核心,负责管理和执行所有的异步任务。它不断检查是否有任务完成并准备执行回调函数,是异步编程能够实现的基础。

  • 回调函数

    回调函数是异步操作完成后被调用的函数。通过回调,程序可以在适当的时候响应异步操作的完成,执行相应的任务。

在JavaScript中,可以完成异步编程的有==定时器==,==AJAX==,以及ES6中引入的==promise==。

5.3 AJAX(并非是ES6中提出的概念,2005年提出的)

5.3.1 ajax的简介

  • ajax是asynchronous javascript and xml(异步的js和xml)的简写。

  • 是一种用来改善用户体验的技术

  • 其实质是使用XMLHttpRequest对象异步的向服务器发送请求

  • 服务器返回部分数据(减少网络传输),而不是一个完整的页面。

  • 以页面无刷新的效果,更改页面的局部内容。

原理:

1. 当用户进行部分数据验证时,会调用ajax对象。
2. 通过ajax对象向服务器发送请求,同时绑定一个事件处理函数,
3. 当服务器处理完数据后,会返回部分数据,事件处理函数会接收到这一部分数据
4. 从而通过js来完成局部刷新。

总结:ajax,就是异步向服务器发送请求,以达到页面的局部刷新,而不是整个页面刷新的技术。大大改善了用户的体验度。

5.3.2 ajax对象

function getXhr(){var xhr = null;if(window.XMLHttpRequest){ //兼容 IE7+, Firefox, Chrome, Opera, Safarixhr = new XMLHttpRequest();}else{  // 兼容 IE6, IE5 xhr = new ActiveXObject("Microsoft.XMLHttp");}return xhr;
}

5.3.3 常用属性和方法

  • open(method,url)

ajax创建请求,method是请求方式get/post,url是地址
  • send()

ajax发送请求get请求时,参数和参数值写到url上,传入null。post请求,参数和参数值写到send()括号里
  • onreadystatechange

发生任何状态变化时的事件控制对象。1)绑定一个事件处理函数,该函数用来处理readystatechange事件2)当ajax对象的readyState的值发生了改变,比如从0变成了1,就会产生readystatechange事件
  • readyState

表示ajax对象与服务器通信的状态0: 尚未初始化1:正在发送请求2:请求完成3:请求完成,ajax正在接受数据4:ajax接收数据成功
  • responseText

接收服务器返回的文本
  • responseHTML

接收服务区返回的HTML
  • status

服务器返回的HTTP响应的状态码200:  表示请求成功202:  请求被接收,但是处理未完成400:  错误的请求404:  资源未找到500:  服务器代码有问题

5.3.4 ajax编写步骤

1)获取ajax对象:获取XMLHttpRequest对象实例

function getXhr(){var xhr = null;if(window.XMLHttpRequest){xhr = new XMLHttpRequest();}else{xhr = new ActiveXObject("Microsoft.XMLHttp");}return xhr;
}

2)绑定事件回调函数: 为ajax对象的onreadystatechange事件设置响应函数

function fn(){if(xhr.readyState==4 && xhr.status==200){var txt = xhr.responseText;//DOM操作}
}

3)创建请求:调用XMLHttpRequest对象的open方法

// get请求
xhr.open('get','xxx.do',true);
​
注意:true表示发送异步请求!   ajax发送异步请求时,用户仍然可以对当前页面做其他的操作
​
​
// post请求
xhr.open('post','xxx.do',true);
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
​
注意:HTTP协议要求发送post请求时,必须有content-type消息头,但是默认情况下ajax对象不会添加消息头,所以要调用setRequestHeader方法,添加这个消息头。

4)发送请求:调用Ajax对象的send方法

  • get请求:

    • send方法内传递null:

      xhr.send(null)

    • 若要提交数据,则在open方法的“URL”后面追加

      比如xhr.open(‘get’,‘xxx.do?name=value&&name=value’,true)

  • post请求:

    • xhr.send(name=value&&name=value);

5.3.5 案例演示

ajax.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title><style>#wrap{width: 300px;height: 300px;border: 1px solid black;border-radius: 4px;padding: 20px;box-shadow: 2px 2px 1px #ccc;}#wrap > div{margin-top: 20px;}#wrap > div > label{width: 40px;display: inline-block;}#wrap > div > button:nth-child(2){margin-left: 20px;}#box1 {margin-top: 30px;border-top: 1px solid black;padding-top: 20px;}</style>
​
</head>
<body><div id="wrap"><div><label for="name">姓名</label><input id="name" type="text"></div><div><label for="age">年龄</label><input id="age" type="text"></div><div><button id="1" οnclick="sendGet()">get请求</button><button id="2" οnclick="sendPost()">post请求</button></div><div id="box1"></div><div id="box2"></div></div><script>function getXhr(){var xhr = null;if(window.XMLHttpRequest){xhr = new XMLHttpRequest();}else{xhr = new ActiveXObject("Microsoft.XMLHttp")}return xhr;}function sendGet(){var name = document.getElementById("name").value;var age = document.getElementById("age").value;//创建请求var xhr = getXhr();xhr.open('get','testGet?name='+name+'&&age='+age,true);//绑定事件函数,当状态发生改变时,就会执行函数中逻辑,比如0到1的变化xhr.onreadystatechange=function () {//4的时候,表示ajax接收到服务器返回的数据,200表示请求成功if(xhr.readyState==4&&xhr.status==200){var txt = xhr.responseText;document.getElementById("box1").innerText = txt;}};xhr.send(null);}function sendPost(){var name = document.getElementById("name").value;var age = document.getElementById("age").value;var xhr = getXhr();xhr.open('post','testPost',true);// true表示异步,false表示同步//post请求必须设置一个消息头xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")xhr.onreadystatechange=function () {if(xhr.readyState==4&&xhr.status==200){var txt = xhr.responseText;document.getElementById("box2").innerText = txt;}};xhr.send("name="+name+"&&age="+age);}</script>
</body>
</html>
​

AjaxServlet组件

package com.shuilidianli.web;
​
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
​
@WebServlet("/testGet")
public class AjaxServlet extends HttpServlet {
​@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf8");
​String name = req.getParameter("name");String age = req.getParameter("age");System.out.println(name+","+age);PrintWriter pw = resp.getWriter();pw.println("你好!祝你:\n 升官发财, 前途无量");}
}
​

AjaxServlet2组件

package com.shuilidianli.web;
​
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
​
@WebServlet("/testPost")
public class AjaxServlet2 extends HttpServlet {
​@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("utf-8");resp.setContentType("text/html;charset=utf8");
​String name = req.getParameter("name");String age = req.getParameter("age");System.out.println(name+","+age);PrintWriter pw = resp.getWriter();pw.println("你好,"+name+"!送"+age+"岁的你一句诗词:\r 云淡风轻近午天,傍花随柳过前川");}
}

5.4 JQuery对Ajax的支持

5.4.1 JQuery简介

原⽣的JavaScript提供的API操作DOM元素时, 代码⽐较繁琐, 冗⻓. 我们可以使⽤JQuery来操作⻚⾯对象.

jQuery是⼀个快速、简洁且功能丰富的JavaScript框架, 于2006年发布. 它封装JavaScript常⽤的功能代码, 提供了简洁⽽强⼤的选择器和DOM操作⽅法. 使⽤JQuery可以轻松地选择和操作HTML元素,从⽽减少了开发⼈员编写的代码量,提⾼了开发效率,

它提供的 API 易于使⽤且兼容众多浏览器,这让诸如 HTML ⽂档遍历和操作、事件处理、动画和 Ajax 操作更加简单. JQuery对于事件的处理也进⾏了简化, 提供了⼀个简单的API来绑定、触发和处理事件,使开发⼈员能够更⽅便地处理各种交互⾏为.

它也是一个过时的库

所有的库都是为了解决我们开发时的痛点而存在的操作。jQuery解决的问题主要有两个:简化DOM操作,解决浏览器兼容问题。然而随着前端的发展、DOM标准的更新、IE的消亡。DOM操作和浏览器兼容性早已不是什么大问题了,再加上React、Vue、Angular这些大型框架的出现,在实际项目中使用jQuery的机会可以说是少之又少。

因此,在这里我们仅介绍一下,JQuery库里对Ajax支持的部分。

5.4.2 引入库

第一种方式: 引用本地(服务器)的JS文件

image-20240919075706054

第二种方式:使用CDN(内容分发网络,即公共服务器)

字节跳动CDN

<head>
<script src="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js"></script>
</head>

百度CDN

<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">
</script>
</head>

新浪CDN

<head>
<script src="https://lib.sinaapp.com/js/jquery/2.0.2/jquery-2.0.2.min.js">
</script>
</head>

Google CDN

<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
</head>

使用CDN的优势:

1.调用的库在公共服务器上,减少自身服务器的压力。因为我们服务不需要通过我们自身服务器去加载文件。
2.使用人数多,可能很多的网站都在使用这个东西,可以使用到浏览器的缓存,比如a网站使用这个库,b网站也使用,那么用户访问a网站的时候,他会去加装文件,当他去访问b网站的时候,就不用去加装这个文件了。那也可以进一步提示我们的加装速度。

不推荐国外的CDN,因为网络不稳定。

测试是否引用成功:

<script>alert($)//console.log($)      $是Jquery对象,如果打印出来内容,就说明引用成功
</script>

5.4.3 常用函数

1)load()

作用:向服务器发送请求,并将服务器返回的数据添加被选中的元素中。
语法:$(selecter).load(URL,Data [,callback] )URL:  向服务器发送的请求路径Data: 请求参数可以是字符串形式:“username=zhangsan&age=22”可以是对象形式:{"username":"zhangsan","age":23}有请求参数时,发送post,否则发送get

2)get()/post()

作用:get()和 post()方法分别用于通过HTTP GET 和POST 请求向服务器发送请求。
语法:$.post(URL,data,callback,dataType)URL:发送请求的 URL字符串。data:可选的,发送给服务器的字符串或 key/value 键值对。callback:可选的,请求成功后执行的回调函数。dataType:可选的,从服务器返回的数据类型。默认:智能推断(可以是html,text,xml, json, script)。 注意:get()可能返回浏览器缓存数据,post()不会返回缓存数据      

3)ajax()

ajax()用法:$obj.ajax({});url:请求地址data:请求参数type:请求方式dataType:返回的数据类型success:正常时的回调函数error:错误时的回到函数async:true默认值,当值为false时,发送同步请求

5.5 回调地狱

回调地狱这个词听起来就非常的高大上,想要接触Promise之前,必须要懂得什么是回调地狱,以及为什么会产生回调地狱?

先来看看概念:当一个回调函数嵌套一个回调函数的时候就会出现一个嵌套结构,当嵌套的多了就会出现回调地狱的情况。

根据前面我们可以得出一个结论:存在异步任务的代码,不能保证能按照顺序执行,那如果我们非要代码顺序执行呢?

举个例子:让四个回调函数打印骆宾王的《咏鹅》,咱们必须要这样操作,才能保证顺序正确:

setTimeout(function () {setTimeout(function () {setTimeout(function () {setTimeout(function () {console.log("红掌拨清波")}, 1000)console.log("白毛浮绿水")}, 2000)console.log("曲项向天歌")}, 3000)console.log("鹅鹅鹅")
}, 4000)

可以看到,代码中的回调函数套回调函数,居然套了4层,这种回调函数中嵌套回调函数的情况就叫做回调地狱。

总结一下,回调地狱就是为实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。

那该如何解决回调地狱呢?

1. 使用ES6引入的promise
2. async/await

5.6 promise的应用

Promise是js中的一个原生对象(也可以理解为一个类或者一个构造函数),是一种异步编程的解决方案,可以替换掉传统的回调函数解决方案。

Promise是一种对异步操作的封装,表示一个操作现在可能还没有完成,但将来会完成,并提供了成功或失败时要执行的操作。

5.6.1 Promise的三种状态

pending
fulfilled
rejected

5.6.2 Promise的参数

Promise构造函数的参数,需要我们传入一个函数,我们需要处理的异步任务就是书写在该函数体内。传入的这个函数,要求必须要有两个参数,第一个参数是异步任务执行成功时的回调函数,第二个参数是异步任务执行失败时的回调函数,正常来说,参数名叫什么都无所谓,但是咱们尽量做到见名知意嘛,所以规范中命名为resolve(解决的含义),reject(拒绝)。异步任务执行成功时调用resolve函数返回结果,反之调用reject。

let p = new Promise((resolve, reject) => {//伪代码let t = Math.round(Math.random() * 10)console.log(t);if (t <= 7) {resolve("成功执行了")} else {reject("执行失败了")}
})

5.4.3 常用API

  • then()

    Promise对象的then方法用来接收处理成功时响应的数据,
  • catch()

    catch方法用来接收处理失败时相应的数据。

5.7 Async/Await

Async/await是建立在Promises之上的语法糖,使得异步代码的编写和理解更接近传统的同步代码风格。(使用同步的方式编写异步代码)

5.7.1 Async关键字

声明函数时,在前面添加Async关键字,表示该函数为一个异步任务,不会阻塞后面函数的执行。

async function fn(){return '任务1';
}
console.log(fn());   // Promise{fulfilled: "任务1"}

打印可以看到async函数返回数据时自动封装为一个Promise对象。

和Promise对象一样,处理异步任务时也可以按照成功和失败来返回不同的数据,处理成功时用then方法来接收,失败时用catch方法来接收数据:

async function fn() {var flag = true;if (flag) {return '任务1--成功';}else{throw '任务1-失败'}
}
fn().then(data=>{console.log(data);
}).catch(data=>{console.log(data);
})
​
console.log('先执行我,表明async声明的函数是异步的');

5.7.2 Await关键字

  • await关键字只能在使用async定义的函数中使用

  • await后面可以直接跟一个 Promise实例对象(可以跟任何表达式,更多的是跟一个返回Promise对象的表达式)

  • await函数不能单独使用

  • await可以直接拿到Promise中resolve中的数据。

        //封装一个返回promise的异步任务function fn(str) {var p = new Promise(function (resolve, reject) {var flag = true;setTimeout(function () {if (flag) {resolve(str)} else {reject('处理失败')}})})return p;}
​//封装一个执行上述异步任务的async函数async function test(){var res1=await fn('任务1');  //await直接拿到fn()返回的promise的数据,并且赋值给resvar res2=await fn('任务2');var res3=await fn('任务3');console.log(res1,res2,res3);}//执行函数test();

5.8 Axios

5.8.1 Axios简介

Axios(中文谐音:爱克丝赛欧斯)

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

官方网站:http://www.axios-js.com

源码:https://gitee.com/charlinchenlin/store-pos

特性:

1、从浏览器中创建 XMLHttpRequests

2、从 node.js 创建 http 请求

3、支持 Promise API

4、拦截请求和响应

5、转换请求数据和响应数据

6、取消请求

7、自动转换 JSON 数据

8、客户端支持防御 XSRF

5.8.2 安装方式

使用 npm:

$ npm install axios

使用 bower:

$ bower install axios

使用CDN

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

5.8.3 案例演示

<!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>Document</title><!-- 本地引入axios --><script src="000/axios-master/lib/axios.js"</script><!--  -->
</head>
<body><button id="btn">axios使用get提交数据</button><button id="btn1">axios使用post提交数据</button><button id="btn2">直接使用axios发送get提交数据</button><button id="btn3">直接使用axios发送post提交数据</button><script>var btn = document.querySelector("#btn");btn.addEventListener("click",function (params) {var url = "http://www.liulongbin.top:3006/api/get";var paramsobj = {name:'zs',age:20};axios.get(url,{params:paramsobj}).then(function (res) {var data = res.data;console.log(data);});});document.querySelector("#btn1").addEventListener("click",function (params) {var url = "http://www.liulongbin.top:3006/api/post";var dataobj = {location:'zs',address:'zs'};axios.post(url,{params:dataobj}).then(function (res) {console.log(res.data);});})document.querySelector("#btn2").addEventListener("click",function (params) {var url = "http://www.liulongbin.top:3006/api/get";var paramsdata = {name:'zss',age:20};axios({url:url,method:'GET',params:paramsdata}).then(function (res) {console.log(res.data);});});document.querySelector("#btn3").addEventListener("click",function (params) {var url = "http://www.liulongbin.top:3006/api/post";var paramsdataa = {name:'钢铁侠',age:35};axios({url:url,method:'POST',data:paramsdataa}).then(function (res) {console.log(res.data);});});</script>
</body>
</html>

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

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

相关文章

GNU编译器(GCC):编译的4个过程及.elf、.list、.map文件功能说明

0 参考资料 GNU-LD-v2.30-中文手册.pdf GNU linker.pdf1 前言 一个完整的编译工具链应该包含以下4个部分&#xff1a; &#xff08;1&#xff09;编译器 &#xff08;2&#xff09;汇编器 &#xff08;3&#xff09;链接器 &#xff08;4&#xff09;lib库 在GNU工具链中&…

开源 AI 智能名片 S2B2C 商城小程序与营销工具的快速迭代

摘要&#xff1a;本文以开源 AI 智能名片 S2B2C 商城小程序为研究对象&#xff0c;探讨在营销工具快速迭代的背景下&#xff0c;该小程序如何借鉴以拼多多为代表的“小程序拼团”、以蘑菇街为代表的“小程序直播”、以花点时间为代表的“小程序按月订花”等经典案例&#xff0c…

数据集-目标检测系列-摩托车检测数据集 motorcycle >> DataBall

数据集-目标检测系列-摩托车检测数据集 motorcycle >> DataBall 数据集-目标检测系列-摩托车&#xff08;motorcycle&#xff09;检测数据集 数据量&#xff1a;1W 想要进一步了解&#xff0c;请联系 DataBall。 DataBall 助力快速掌握数据集的信息和使用方式&#xf…

《论软件架构建模技术与应用》写作框架,软考高级系统架构设计师

论文真题 软件架构风格是描述一类特定应用领域中系统组织方式的惯用模式&#xff0c;反映了领域中诸多系统所共有的结构特征和语义特征&#xff0c;并指导如何将各个模块和子系统有效组织成一个完整的系统。分层架构是一种常见的软件架构风格&#xff0c;能够有效简化设计&…

Python语法进阶之路

一、Python基础 1.1 注释 定义和作用 对代码解释说明&#xff0c;增强可读性 单行注释 # 多行注释 """ 这是一个多行注释 """ 1.2 变量及变量类型 定义和作用 计算机目的是计算&#xff0c;编程是为了更方便计算&#xff0c;计算对象就是…

论前端框架的对比和选择 依据 前端框架的误区

前端框架的对比和选择依据 在前端开发中&#xff0c;有多种框架可供选择&#xff0c;以下是一些常见前端框架的对比和选择依据&#xff1a; 一、Vue.js 特点&#xff1a; 渐进式框架&#xff0c;灵活度高&#xff0c;可以逐步引入到项目中。学习曲线相对较平缓&#xff0c;容…

Attention is All You Need精读

原文开头&#xff0c;不是搬运 dog。All attention is all you need Abstract 摘要 这篇文章的内容源于基于编码器-解码器架构的RNN模型&#xff0c;在其他人的工作中&#xff0c;我们可以发现注意力机制对于提升编码器-解码器架构模型的性能很重要。这篇文章提出了一个比较简…

SpringBoot 更改启动图标

每次springboot开启时&#xff0c;开会显示spring的图标&#xff0c;这个图标是可以修改的。 一、原始的图标样式 二、修改图标样式 https://patorjk.com/software/taag/#pdisplay&fGraffiti&thttps://patorjk.com/software/taag/#pdisplay&fGraffiti&t 在…

MMROTATE 1.X特征图可视化(绘制Heat Map)

本文参考MMYOLO官方的特征图可视化教程&#xff0c;对MMROTATE相关算法进行特征图可视化 1. 新建featmap_vis_demo.py文件 在mmrotate项目文件夹下新建 featmap_vis_demo.py &#xff1a; # Copyright (c) OpenMMLab. All rights reserved. import argparse import os from t…

“吉林一号”宽幅02B系列卫星

离轴四反光学成像系统 1.光学系统参数&#xff1a; 焦距&#xff1a;77.5mm&#xff1b; F/#&#xff1a;7.4&#xff1b; 视场&#xff1a;≥56゜&#xff1b; 光谱范围&#xff1a;400nm&#xff5e;1000nm。 2.说明&#xff1a; 光学系统采用离轴全反射式结构&#xff0c;整…

CIM平台应用的一些思考

今天中午看了一些书&#xff0c;讲致幻剂在疾病治疗的一些作用。致幻剂包括毒蘑菇等这类东西&#xff0c;有精神疾病或其他心里疾病的患者在吸食或注射&#xff08;专业医生的指导下&#xff09;会忘记或减轻身体的痛苦&#xff0c;忘记死亡&#xff0c;相信永生&#xff0c;治…

VMWare虚拟机安装CentOS-7-x86_64-DVD-1611操作系统

VMWare虚拟机安装CentOS7操作系统 1、虚拟机准备打开VMware单机创建新的虚拟机典型与自定义安装选择虚拟机硬件兼容性选择安装程序光盘映射文件(iso)选择客户机操作系统命名虚拟机处理器配置内存配置网络连接类型I/O类型选择磁盘类型选择磁盘指定磁盘的最大磁盘大小磁盘名称我们…

高中数学:立体几何-平面的定义与公理

文章目录 一、平面定义及画法1、定义2、表示方法 二、公理1、公理12、公理23、公理3 一、平面定义及画法 1、定义 平面是向四周无限延展的。 2、表示方法 我们常用矩形的直观图&#xff0c;即平行四边形表示平面&#xff0e; 我们常用希腊字母α&#xff0c;β&#xff0c…

八. 实战:CUDA-BEVFusion部署分析-coordTrans Precomputation

目录 前言0. 简述1. 案例运行2. coordTrans3. Precomputation总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第八章—实战&#xff1a;CUDA-BEVFusion部署分…

『正版软件』XYplorer 专业的 Windows 文件管理工具软件

在数字化时代&#xff0c;我们每天都在与各种文件打交道。无论是工作文档、个人照片还是多媒体资料&#xff0c;管理这些文件的效率直接关系到我们的工作效率和生活体验。今天&#xff0c;我要向大家推荐一款功能强大、操作简便的文件管理软件 —— XYplorer。 XYplorer&#x…

【小bug】使用 RestTemplate 工具从 JSON 数据反序列化为 Java 对象时报类型转换异常

起因&#xff1a;今天编写一个请求时需要通过RestTemplate调用外部接口&#xff0c;获取一些信息&#xff0c;但是在获取了外部接口响应内容后&#xff0c;使用强制转换发现报了类型转换异常。之前也遇到过&#xff0c;但是没记录下来&#xff0c;今天又查了一遍……干脆记录一…

【hot100-java】【搜索旋转排序数组】

R8-二分查找篇 等等&#xff0c;不是&#xff1f;O(logn)&#xff1f;那岂不是一次遍历数组都超时了hh. 二分查找分类 class Solution {public int search(int[] nums, int target) {if (numsnull||nums.length0){return -1;}int start0;int endnums.length-1;int mid;while …

以太坊客户端Geth的介绍与搭建

一、以太坊客户端 1.介绍 以太坊客户端是指用于连接、交互和参与以太坊区块链网络的软件。以太坊客户端允许用户执行各种操作&#xff0c;如发送交易、挖矿、部署智能合约、同步区块链数据等。 2.功能 区块链同步&#xff1a;客户端会下载并验证以太坊区块链的所有区块&…

windows 出现身份验证错误,要求的函数不受支持

现象环境&#xff1a; win10 mstsc内网远程server2016&#xff0c;出现错误代码&#xff1a; 远程桌面连接出现身份验证错误。要求的函数不受支持。这可能是由于CredSSP加密数据库修正 出现身份验证错误 原因&#xff1a; 系统更新&#xff0c;微软系统补丁的更新将 Cred…

【Godot4.3】2D程序生成植物概论

概述 Godot的2D程序化植物生成是我一直想要探讨的一个内容&#xff0c;但是一直没有真正开动&#xff0c;在刚过去的中秋节假期期间&#xff0c;在老家无聊&#xff0c;在一个素描本上构思了一系列想法。本篇就基于这些自己的想法介绍一下程序化植物生成的基本思路。不一定对&…