Ajax
1.Ajax原理
浏览器中的线程状态:
js是单线程的,那么是否代表参与js执行过程的线程就只有一个?
不是的,会有四个线程参与该过程,但是永远只有JS执行引擎线程在执行JS脚本程序,其他的三个线程只协助,不参与代码解析与执行。参与js执行过程的线程分别是:
JS****执行引擎线程: 也称为JS内核,负责解析执行Javascript脚本程序的主线程(例如V8引擎)
事件触发线程: 归属于浏览器内核进程,不受JS引擎线程控制。主要用于控制事件(例如鼠标,键盘等事件),当该事件被触发时候,事件触发线程就会把该事件的处理函数推进事件队列,等待JS引擎线程执行
定时器触发线程:主要控制计时器setInterval和延时器setTimeout,用于定时器的计时,计时完毕,满足定时器的触发条件,则将定时器的处理函数推进事件队列中,等待JS引擎线程执行。
注:W3C在HTML标准中规定setTimeout低于4ms的时间间隔算为4ms。
HTTP异步请求线程:通过XMLHttpRequest连接后,通过浏览器新开的一个线程,监控readyState状态变更时,如果设置了该状态的回调函数,则将该状态的处理函数推进事件队列中,等待JS引擎线程执行。
注:浏览器对通一域名请求的并发连接数是有限制的,Chrome和Firefox限制数为6个,ie8则为10个。
总结:永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引擎线程执行。
ajax由js编写,使用XMLHttpRequest 对象对数据收发进行封装,
发送ajax请求时,ajax会要求调用方(浏览器)开启新线程向服务器进行请求,并对响应的结果进行反复读取,当读取到特定状态后,停止反复读取。读取过程中会把需要运行的js(回调函数)添加入js的执行队列(js执行引擎为单线程),js执行引擎按队列顺序执行。
2. 原生ajax代码步骤
-
创建XMLHttpRequest对象
-
设置回调函数
-
初始化XMLHttpRequest组件(设置)
-
发送请求
//异步请求 局部刷新(通过回调函数 控制服务器返回的数据) 无刷新(接收到响应数据后 浏览器不跳转)
//发送异步请求 通过回调函数 处理服务器的响应数据
//回调函数的处理需要与服务器响应数据搭配
<%--
Created by IntelliJ IDEA.
User: JAVASM
Date: 2020/8/15
Time: 10:03
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
<script src="js/jquery-3.4.1.min.js">
</script>
<script>
$(function(){
$("#myBtn").click(function(){
myAjaxReq();
})
})
//原生ajax调用过程
function myAjaxReq(){
//XMLHttpRequest ajax核心对象
var xmlhttp;
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//回调函数 当请求正常返回时 用js操作页面
xmlhttp.onreadystatechange=function(){
//readyState ajax请求的状态 4代表请求发送完成
//status http的状态 200代表正确返回
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//处理响应的代码
//xmlhttp.responseText 获取服务器响应的数据
console.log(xmlhttp.responseText);
document.getElementById("showRes").innerHTML=xmlhttp.responseText;
}
}
//设置请求的地址 方式 是否使用异步
//初始化异步请求对象
xmlhttp.open("POST","ajaxDemo",true);
//设置请求头
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
//设置发送的参数
//method不同 发送数据的格式不同?
xmlhttp.send("mytest="+document.getElementById("mytext").value);
}
</script>
</head>
<body>
<input id="myBtn" type="button" value="发送异步请求">
<hr>
<input id="mytext" type="text">
<span id="showRes"></span>
</body>
</html>
- XMLHttpRequest对象的属性和方法
注意:使用ajax时参数需要自己传递,get方式把参数直接拼接在url后,post方式把参数写在send方法的参数中。
3. JqueryAjax
原生ajax配置格式不规整,使用使用时经常使用jquery优化后的ajax
//jquery封装的ajax请求
//通过json格式设置参数
$.ajax({
url:"ajaxServlet",//地址
type:"post",//请求类型
data:{"uname":$("#username").val()}, //请求的参数 常用json格式
dataType:"text",//返回数据的类型
success:function(data){//响应成功时的回调函数 data表示返回的数据
console.log(data);
}
});
//例子:
<script>
$(function(){
$("#myBtn").click(function(){
$.ajax({
url:"ajaxDemo",//地址
type:"post",//请求类型
data:{"mytest":$("#mytext").val()}, //请求的参数 常用json格式 或者普通键值对 一般用json格式
//普通键值对---{"mytest":$("#mytext").val()}
dataType:"json",//返回数据的类型
success:function(data){//响应成功时的回调函数 data表示返回的数据
console.log(data);
$("#showRes").html(data);
}
});
//简化格式
$.get("ajaxDemo",
"mytest":$("#mytext").val() //"mytest="+$("#mytext").val()+"&test=abc123",
function(data){
console.log(data);
},"text")
})
})
</script>
Jquery中简化ajax,json格式改为固定参数
$.post(
//发送的请求地址
//要发送的数据key/value,
//回调函数,
//返回内容格式,xml,html,script,json,text
)
$.get(
//发送的请求地址
//要发送的数据key/value,
//回调函数,
//返回内容格式,xml,html,script,json,text
)
进一步简化
.getJSON(
“发送地址”,
发送参数,
回调函数
)
注意1:使用ajax时,需要自己拼接参数,可以使用$("#myform").serialize(),把form序列化成键值对字符串格式。
注意2:后台可以借助fastJSON工具,给前台返回json格式字符串。
// ajax使用例子
//定义响应码 10000 成功 10001 有点成功 20000失败 20001 有点失败
//回调返回的数据 传json 拼成标准json格式 key带引号
//gson jackson fastjson(China 阿里 用它)
//returnCode returnMSG returnData
//为了让返回数据标准化
/*
* ReturnEntity 规范返回数据的key
* ReturnCode 规范返回数据的 Code MSG 的值
*/
//ReturnCode 规范返回数据的 Code MSG 的值
public enum ReturnCode {
SUCCESS(10000,"操作成功"),
FAILED(20000,"操作失败"),
UNAME_OK(10001,"用户名可用"),
UNAME_DUPLICATE(20001,"用户名重复");
Integer code;
String msg;
private ReturnCode(Integer code,String msg){
this.code = code;
this.msg = msg;
}
public Integer getCode() { return code; }
public String getMsg() { return msg; }
}
//ReturnEntity 规范返回数据的key
public class ReturnEntity {
//returnCode returnMSG returnData
private Integer returnCode;
private String returnMSG;
private List returnData;
public Integer getReturnCode() {return returnCode;}
public void setReturnCode(Integer returnCode) {this.returnCode = returnCode;}
public String getReturnMSG() {return returnMSG;}
public void setReturnMSG(String returnMSG) {his.returnMSG = returnMSG;}
public List getReturnData() {return returnData;}
public void setReturnData(List returnData) {this.returnData = returnData;}
public ReturnEntity(Integer returnCode, String returnMSG, List returnData) {
this.returnCode = returnCode;
this.returnMSG = returnMSG;
this.returnData = returnData;
}
public ReturnEntity() {
}
}
//异步调用的页面
@WebServlet("/checkUname")
public class CheckServlet 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 {
ReturnEntity reEntity = new ReturnEntity();
req.setCharacterEncoding("utf-8");
String uname = req.getParameter("uname");
resp.setContentType("text/html;charset=utf-8");
PrintWriter writer = resp.getWriter();
String resStr = "";
if("jack".equals(uname)){
reEntity.setReturnCode(ReturnCode.UNAME_DUPLICATE.getCode());
reEntity.setReturnMSG(ReturnCode.UNAME_DUPLICATE.getMsg());
}else{
reEntity.setReturnCode(ReturnCode.UNAME_OK.getCode());
reEntity.setReturnMSG(ReturnCode.UNAME_OK.getMsg());
}
resStr = JSON.toJSONString(reEntity); // fastjson(China 阿里 用它) 将数据转换成了json串
writer.print(resStr);
writer.flush();
writer.close();
}
}
//显示页面
<%--
Created by IntelliJ IDEA.
User: JAVASM
Date: 2020/8/15
Time: 10:51
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
<style>
.mysuccess{
color: greenyellow;
}
.myfailed{
color: lightcoral;
}
</style>
<script src="js/jquery-3.4.1.min.js">
</script>
<script>
$(function(){
$("#uname").change(function() //文本框改变发启用
$.post("checkUname",{"uname":$(this).val()},function(data){
if(10001==data.returnCode){
$("#checkNameSpan").removeClass("myfailed")
$("#checkNameSpan").addClass("mysuccess")
}else if(20001==data.returnCode){
$("#checkNameSpan").removeClass("mysuccess")
$("#checkNameSpan").addClass("myfailed")
}
$("#checkNameSpan").html(data.returnMSG);
},"json")
})
})
</script>
</head>
<body>
<form action="/day5/regist" method="post">
<input id="uname" type="text" placeholder="请输入用户名"><span id="checkNameSpan"></span><br>
<input type="text" placeholder="请输入密码"><br>
<input type="text" placeholder="请输入电话"><br>
<input type="text" placeholder="请输入邮箱"><br>
<input type="submit"><br>
</form>
</body>
</html>