JavaScrit异步编程

本文深入浅出地介绍了异步编程的概念,如何在前端处理耗时操作,以及如何解决AJAX跨域问题。通过实例演示了AJAX的使用和CORS策略的调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

异步的概念

异步(Asynchronous, async)是与同步(Synchronous, sync)相对的概念。

在我们学习的传统单线程编程中,程序的运行是同步的(同步不意味着所有步骤同时运行,而是指步骤在一个控制流序列中按顺序执行)。而异步的概念则是不保证同步的概念,也就是说,一个异步过程的执行将不再与原有的序列有顺序关系。

简单来理解就是:同步按你的代码顺序执行,异步不按照代码顺序执行,异步的执行效率更高。

以上是关于异步的概念的解释,接下来我们通俗地解释一下异步:异步就是从主线程发射一个子线程来完成任务。

 

同步:步骤在一个控制流序列中按顺序执行,不意味着所有步骤同时运行.

异步:是从控制流序列【主线】开辟一个子控制流序列【副本】来完成任务。

同步程序执行效率低,异步程序执行效率高。

异步程序缺点:子线程脱离主线程控制,主线程不能判断子线程是否执行完毕,不子线程的执行结果不能直接合并到主线程中。

什么时候用异步编程

在前端编程中(甚至后端有时也是这样),我们在处理一些简短、快速的操作时,例如计算 1 + 1 的结果,往往在主线程中就可以完成。主线程作为一个线程,不能够同时接受多方面的请求。所以,当一个事件没有结束时,界面将无法处理其他请求。

现在有一个按钮,如果我们设置它的 onclick 事件为一个死循环,那么当这个按钮按下,整个网页将失去响应。

为了避免这种情况的发生,我们常常用子线程来完成一些可能消耗时间足够长以至于被用户察觉的事情,比如读取一个大文件或者发出一个网络请求。因为子线程独立于主线程,所以即使出现阻塞也不会影响主线程的运行。但是子线程有一个局限:一旦发射了以后就会与主线程失去同步,我们无法确定它的结束,如果结束之后需要处理一些事情,比如处理来自服务器的信息,我们是无法将它合并到主线程中去的。

为了解决这个问题,JavaScript 中的异步操作函数往往通过回调函数来实现异步任务的结果处理。

异步 AJAX

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

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

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

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

AJAX 工作原理

 

 AJAX 实例

例如:html页面发送http请求到服务器,得到一组学生信息,将得到的学生信息显示在html页面的表格中。

开发服务器程序

  1. 安装配置开发工具。
  2. 打开eclipse新建一个Maven项目

问题1:项目默认的java开发库版本【J2SE-1.5】与我们自己安装的java开发库版本【javase-1.8】不一致

解决方法:在项目中的pom.xml配置插件

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>  
  </build>

选中项目---右键---Maven---update project

问题2:web.xml is missing and <failOnMissingWebXml> is set to true

解决:在当前项目的src-->main-->webapp文件夹下创建WEB-INF文件夹;

在WEB-INF文件夹中创建web.xml文件

 web.xml文件中的内容

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  
</web-app>

3.创建构造学生信息的java类

创建保存java类的程序包“src/main/java”--右键--->new--->other--->java---package

“com.wangxing.javabean”

package com.wangxing.javabean;
/**
 * 创建学生信息的java类
 * @author Administrator
 *
 */
public class Student {
	private int stuid;
	private String  stuname;
	private int  stuage;
	private String stuaddress;
	public  Student(int stuid,String  stuname,int  stuage,String stuaddress){
		this.stuid=stuid;
		this.stuname=stuname;
		this.stuage=stuage;
		this.stuaddress=stuaddress;
	}
	public int getStuid() {
		return stuid;
	}
	public void setStuid(int stuid) {
		this.stuid = stuid;
	}
	public String getStuname() {
		return stuname;
	}
	public void setStuname(String stuname) {
		this.stuname = stuname;
	}
	public int getStuage() {
		return stuage;
	}
	public void setStuage(int stuage) {
		this.stuage = stuage;
	}
	public String getStuaddress() {
		return stuaddress;
	}
	public void setStuaddress(String stuaddress) {
		this.stuaddress = stuaddress;
	}
}

4.在项目的pom.xml文件中配置servlet的依赖库,和gson的依赖库

<dependencies>
		<!-- 配置导入servlet的依赖库 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
			<scope>provided</scope>
		</dependency>
<!-- 配置导入gson的依赖库 -->
		<dependency>
			<groupId>com.google.code.gson</groupId>
			<artifactId>gson</artifactId>
			<version>2.8.2</version>
		</dependency>
</dependencies>

5. 编写请求处理程序

创建保存请求处理程序的程序包“src/main/java”--右键--->new--->other--->java---package

“com.wangxing.servlet”

package com.wangxing.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.wangxing.javabean.Student;

/**
 * 请求的处理程序
 * @author Administrator
 *
 */
public class StudentServlet extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//创建学生信息对象【一组】
		Student stu1=new Student(1001,"zhangsan",23,"西安");
		Student stu2=new Student(1002,"lisisi",24,"北京");
		Student stu3=new Student(1003,"wangwu",25,"上海");
		//创建保存学生信息的集合
		List<Student> stulist=new ArrayList<Student>();
		//装学生信息对象到集合
		stulist.add(stu1);
		stulist.add(stu2);
		stulist.add(stu3);
		//将装有学生信息对象到集合转换成json字符串
		Gson gson=new Gson();
		String studentjson=gson.toJson(stulist);
		//设置请求对象/响应对象的字符编码
		req.setCharacterEncoding("utf-8");
		resp.setCharacterEncoding("utf-8");
		//创建输出流对象
		PrintWriter out=resp.getWriter();
		//写出json字符串
		out.write(studentjson);
		//关闭
		out.close();
	}
}

6.配置请求处理程序

WEB-INF/web.xml

<servlet>
  	<servlet-name>student</servlet-name>
  	<servlet-class>com.wangxing.servlet.StudentServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>student</servlet-name>
  	<url-pattern>/getStudent</url-pattern>
 </servlet-mapping>

7.在pom.xml配置tomcat服务器插件

<!-- 配置Tomcat插件 -->
			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<!-- 服务器访问端口号 -->
					<port>8080</port>
					<!--项目访问路径 -->
					<path>/</path>
					<!--服务器编码 -->
					<uriEncoding>UTF-8</uriEncoding>
				</configuration>
		     </plugin>

8.运行服务器

项目---》右键--》run as ---》Maven  build---Goals:tomcat7:run

9.浏览器输入:http://localhost:8080/getStudent

 页面开发

创建HTML页面。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <script>
            window.onload=function(){
                //得到按钮对象
                var butdom=document.getElementById("but1");
                //绑定点击事件
                butdom.onclick=function(){
                    //发起ajax请求
                    //1.创建XMLHttpRequest对象
                    //现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建XMLHttpRequest对象
                    //老版本的Internet Explorer (IE5 和 IE6)使用 ActiveX 对象
                    var httpRequest=null;
                    if(window.XMLHttpRequest){
                        httpRequest=new XMLHttpRequest();
                    }else{
                        httpRequest=new ActiveXObject("Microsoft.XMLHTTP")
                    }
             
                //2.建立连接
                //通过XMLHttpRequest对象的open方法完成
                //open(method,url,async)
                //method--请求的类型; GET或POST
                //url ---服务器位置
                //async--true(异步)或false(同步)
                httpRequest.open("GET","http://localhost:8080/getStudent",true);
                //3.发送请求
                //通过XMLHttpRequest对象的send方法完成
                httpRequest.send();
                httpRequest.onreadystatechange=function(){
                //接受结果
                //通过XMLHttpRequest对象的属性readyState属性
                //0: 请求未初始化
                //1: 服务器连接已建立
                //2: 请求已接收
                //3: 请求处理中
                //4: 请求已完成,且响应已就绪
                //判断请求是否处理成功
                //通过XMLHttpRequest对象的status属性
                //200:"ok"// 404: 未找到页面  //500: 服务器错误
                if(httpRequest.readyState==4&&httpRequest.status==200){
                    //得到服务器返回json字符串数据
                    
                    //通过XMLHttpRquest独享的responseText属性
                    var data=httpRequest.responseText;
                    //处理json字符串
                    //alert(data);
                    var json1=JSON.parse(data);
                    //alert(json1);
                    var tab1=document.getElementById("tab1");
                    var tostring="<tr><td>学好</td><td>姓名</td><td>年龄</td><td>地址</td></tr>"
                   
                    for(var index in json1){
                        var datetab="<tr><td>"+json1[index].stuid+
                        "</td><td>"+json1[index].stuname+
                        "</td><td>"+json1[index].stuage+"</td><td>"+json1[index].stuaddress+"</td></tr>"
                        
                        tostring=tostring+datetab
                    }
                    tab1.innerHTML=tostring;
                }
            }
            }
            }
        </script>
    </head>
    <body>
        <input type="button" value="得到学生信息" id="but1">
        <table id="tab1" border="1px"></table>
    </body>
</html>

问题: Access to XMLHttpRequest at 'http://localhost:8080/getStudent' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.[跨域资源共享 CORS]

[http://www.ruanyifeng.com/blog/2016/04/cors.html]

解决方法:

1.在当前HTML页面中进行设置[不推荐]

2.将http请求对象的设置交给服务器来完成

修改服务器程序

创建保存过滤器的程序包“com.wangxing.filte”

package com.wangxing.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class CORSFilter implements Filter{
	 @Override
	  public void init(FilterConfig filterConfig) throws ServletException {
	  }
	
	  @Override
	  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
	    	HttpServletResponse response = (HttpServletResponse) servletResponse;
	    	response.setHeader("Access-Control-Allow-Origin", "*");
	    	response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
	    	response.setHeader("Access-Control-Max-Age", "3600");
	    	response.setHeader("Access-Control-Allow-Headers", "content-type,Authorization");
	    	// response.setHeader("Access-Control-Allow-Credentials", "true");
	    	filterChain.doFilter(servletRequest, servletResponse);
	  }
	  @Override
	  public void destroy() {
	  }
}

在web.xml配置CORSFilter 过滤器

注意:过滤器配置信息要写在servlet请求处理程序之前

<filter>
  	<filter-name>corsfilter</filter-name>
  	<filter-class>com.wangxing.filter.CORSFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>corsfilter</filter-name>
  	<url-pattern>/*</url-pattern>
  </filter-mapping>

 XMLHttpRequest 对象

所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。

XMLHttpRequest 用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

创建 XMLHttpRequest 对象

所有现代浏览器(IE7+、Firefox、Chrome、Safari 以及 Opera)均内建 XMLHttpRequest 对象。

创建 XMLHttpRequest 对象的语法:

variable=new XMLHttpRequest();

老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:

variable=new ActiveXObject("Microsoft.XMLHTTP");

为了应对所有的现代浏览器,包括 IE5 和 IE6,请检查浏览器是否支持 XMLHttpRequest 对象。如果支持,则创建 XMLHttpRequest 对象。如果不支持,则创建 ActiveXObject .

var xmlhttp;
if (window.XMLHttpRequest){
		//  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
		xmlhttp=new XMLHttpRequest();
}else{
		// IE6, IE5 浏览器执行代码
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}

AJAX - 向服务器发送请求

如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open() 和 send() 方法

xmlhttp.open("GET","ajax_info.txt",true);

xmlhttp.send();

方法

描述

open(method,url,async)

规定请求的类型、URL 以及是否异步处理请求。

method:请求的类型;GET 或 POST

url:文件在服务器上的位置

async:true(异步)或 false(同步)

send(string)

 

将请求发送到服务器。

string:仅用于 POST 请求

GET 还是 POST?

与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。

然而,在以下情况中,请使用 POST 请求:

无法使用缓存文件(更新服务器上的文件或数据库)

向服务器发送大量数据(POST 没有数据量限制)

发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠

 

 GET 请求

xmlhttp.open("GET","/try/ajax/demo_get2.php?fname=Henry&lname=Ford",true);
xmlhttp.send();

POST 请求

xmlhttp.open("POST","/try/ajax/demo_post.php",true);
xmlhttp.send();

如果需要像 HTML 表单那样 POST 数据,请使用 setRequestHeader() 来添加 HTTP 头。然后在 send() 方法中规定您希望发送的数据.

xmlhttp.open("POST","/try/ajax/demo_post2.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("fname=Henry&lname=Ford");

AJAX - 服务器 响应

如需获得来自服务器的响应,请使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性。

属性

描述

responseText

获得字符串形式的响应数据。

responseXML

获得 XML 形式的响应数据。

AJAX - onreadystatechange 事件 

当请求被发送到服务器时,我们需要执行一些基于响应的任务。

每当 readyState 改变时,就会触发 onreadystatechange 事件。

readyState 属性存有 XMLHttpRequest 的状态信息。

下面是 XMLHttpRequest 对象的三个重要的属性:

属性

描述

onreadystatechange

存储函数(或函数名),每当 readyState 属性改变时,就会调用该函数。

readyState

存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。

0: 请求未初始化

1: 服务器连接已建立

2: 请求已接收

3: 请求处理中

4: 请求已完成,且响应已就绪

status

200: "OK"
404: 未找到页面

 

在 onreadystatechange 事件中,我们规定当服务器响应已做好被处理的准备时所执行的任务。

当 readyState 等于 4 且状态为 200 时,表示响应已就绪.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值