同步与异步

1.同步

  • 严格的按照先后顺序,一步接着一步的执行,等前面完成后才可以执行下一个
  • 例如:食堂排队打饭
consolo.log("a");
consolo.log("b");
consolo.log("c");

2.异步

  • 执行没有严格的先后顺序,两个或多个动作可以同时进行
  • 例如:食堂排队打饭,但是我忘记带饭卡,先让后面同学先,我的饭卡到了我再排队打饭
consolo.log("a");
consolo.log("b");
consolo.log("c");

//异步操作
setTimeout(()=>{consolo.log("我的饭卡拿到了!")},2000);

consolo.log("d");
consolo.log("e");

====》  abcde 我的饭卡拿到了!

Ajax

1.概述

  • 对原生XMLHttpRequest的封装
  • 局部刷新技术

2.XMLHttpRequest

  • Ajax技术核心
  • 作用:发送请求到服务器,接收响应
  • 函数
open(method,URL,async):与服务器建立连接
	1.method:请求的HTTP方法,典型的有GET,POST 
	2.URL:请求的地址 
	3.async:是否使用异步请求 true/false  默认异步
setRequestHeader(header,value):设置请求头信息
	setRequestHeader("HOST","www.baidu.com")//设置主机
	setRequestHeader("AGENT","www.baidu.com")//设置请求头信息
	setRequestHeader("Content-Type","application/x-www-form-urlencoded");
send(content):发送请求
	1.GET只有这一种写法
		req.open("GET","xxx.action?op=reg&name=zy&age=20&sex=男");
		req.send();//写入的参数无效   
	2.POST两种写法都可以
		req.open("POST","xxx.action")
		req.send("op=reg&name=zy&age=20&sex=男");//当然也可以使用get的方式,但get不能只要此方式
  • 属性
onreadystatechange : 绑定回调函数,当服务器有响应时会自动调用
	req.onreadystatechange=function(){.....}
readystate :就绪状态码(引擎状态)
	0 XMLHttpRequest对象没有完成初始化
	1 XMLHttpRequest对象开始发送请求
	2 XMLHttpRequest对象请求发送完成
	3 XMLHttpRequest对象开始读取响应
	4 XMLHttpRequest对象读取响应结果,请求响应成功
status :HTTP状态码(服务器状态)
	200 服务器响应正常
	300 重定向(服务器重新发送一个请求到另一个地址取数据)
	400 无法找到请求的资源,服务器响应正常
	403 没有访问权限
	404 访问的资源不存在
	500 服务器内部错误
responseText :获取响应的文本内容
responseXML :获取响应的XML文件
  • 异步处理
var xmlHttp;

//创建该对象,根据不同的浏览器
function createXMLHttpRequest() {
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();//王景浏览器的创建方式
    }else if(window.ActiveXObject){
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE浏览器的创建方式
    }
}

window.onload = function () {
    getTime();
    getId();
}

function getTime() {
    //创建请求对象
    createXMLHttpRequest();
    //绑定回调函数,当服务器有响应时会自动调用此函数
    xmlHttp.onreadystatechange = handleStatechange;
    //连接服务器
    xmlHttp.open("GET","tools.action?op=date");
    //发送请求
    xmlHttp.send();
}

function handleStatechange() {
    console.log("联机状态state:"+xmlHttp.readyState);
    console.log("服务器状态:"+xmlHttp.status);

    if(xmlHttp.readyState==4 && xmlHttp.status==200){
        console.log(xmlHttp.responseText);

        var json = eval("("+xmlHttp.responseText+")");//完成对象转换
        if(json.code==1){
            document.getElementById("time").innerHTML = "当前系统时间:"+json.data;
        }
    }
}

function getId() {
    //创建请求对象
    createXMLHttpRequest();
    //绑定回调函数
    xmlHttp.onreadystatechange = handleId;
    //连接服务器
    xmlHttp.open("POST","tools.action");
    //通过post是如何编码参数,查文档ajax
    xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    //发送请求
    xmlHttp.send("op=number");
}

function handleId() {
    if(xmlHttp.readyState==4 && xmlHttp.status==200){
        var jsonObject = eval("("+xmlHttp.responseText+")");//完成对象转换
        if(jsonObject.code==1){
            document.getElementById("userid").innerHTML = jsonObject.data;
        }
    }
}
  • 缺点
1.只有等服务器有响应(readyState=4,status=200)才会处理回调函数
2.没法控制顺序,若要保证顺序只能嵌套(太low)
3.两个异步请求时,后一个将前一个覆盖
	解决:xmlHttp变成局部变量或es6 promise**

3.XMLHttpRequest+Promise

  • promise
var xmlHttp;
//创建该对象
function createXMLHttpRequest() {
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();//王景浏览器的创建方式
    }else if(window.ActiveXObject){
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE浏览器的创建方式
    }
}

function promiseAjax(method,url,params) {
    var pp = new Promise(function (resolve,reject){
        createXMLHttpRequest();
        xmlHttp.onreadystatechange = function () {
            if(xmlHttp.readyState!=4)return;
            if(xmlHttp.status==200){
                resolve(xmlHttp.responseText);
            }else{
                reject("!!!");
            }
        }
        xmlHttp.open(method,url);
        xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xmlHttp.send(params);
    });
    return pp;
}

fetch

fetch直接回回送成功还是失败的信息
回送的data也是promise,需要then两次,第二次才会取到json字符串

1.get
	fetch("tools.action?op=date").then(function (data) {
	     //data是一个promise对象
	     //data.text()是一个promise对象  只能访问一次
	     var promise = data.text();
	     return promise;
	 }).then(function (data) {
	     //这里的data才是真正的json字符串    上一个的结果文本
	     var jsonObject = eval("("+data+")");//完成对象转换
	     if (jsonObject.code==1){
	         document.getElementById("time").innerHTML = "当前系统时间:"+jsonObject.data;
	     }
	 })

2.post
	fetch("tools.action?",{
	    method:"post",
	    body:"op=date",//也可以在在tools.action?后面
	    headers:{
	        "Content-Type":"application/x-www-form-urlencoded"
	    }
	}).then(function (data) {
	    return data.text();
	}).then(function (data) {
	    var jsonObject = eval("("+data+")");//完成对象转换
	    if (jsonObject.code==1){
	        document.getElementById("time").innerHTML = "当前系统时间:"+jsonObject.data;
	    }
	})

Axios

1概述

  • 基于promise的HTTP库 - promise
  • 对Ajax的封装
  • 插件,要额外下载

2.优点

  • 从浏览器创建XMLHttpRequest
  • 从node.js创建http请求
  • 支持Promise的API:Promise的内容都可以用到
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF

3.get/post实现

1.get
	axios.get("tools.action?op=date").then(function (data) {
	   console.log(data);
	   console.log(data.data);//json对象
	   console.log(data.data.code);
	   console.log(data.data.data);
	});

2.post----1
	axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded';
	//有中文就要经过转码
	axios({
	    method:'post',
	    url:"tools.action",
	    params:{
	        op:'number'
	    }
	}).then(data => {
	    console.log(data.data.code+"  "+data.data.data);
	});

2.post----2
	axios.defaults.headers.post['Content-Type']='application/x-www-form-urlencoded';
	
	var params = new URLSearchParams();
	params.append('op','date');//包装一下参数
	axios.post('tools.action',params).then(data=>{
	    console.log(data.data.code+"  "+data.data.data);
	})

3.all+spread

  • 作用:在多个请求完成好后再执行一些逻辑
  • 注意:是静态方法,不是实例方法
function getdate() {
    return axios.get("tools.action?op=date");
}
function getnumber() {
    var params = new URLSearchParams();
    params.append('op','number');
    return axios.post("tools.action",params);
}

axios.all([getdate(),getnumber()]).then(
    axios.spread( (d1,d2) => {
        console.log(d1);
        console.log(d1.data.code+"  "+d1.data.data);
        console.log(d2);
        console.log(d2.data.code+"  "+d2.data.data);
    })
)

Axios+Vue+Json

  • 记得导入js(vue+axios)

1.html(页面样式没有)

  • 注意箭头函数与普通函数中this的区别
const app = new Vue({
    el:"#all",
    data:{
        time:'',
        userid:'',
        clientInfo:''
    },
    method:{

    },
    mounted:function () {//页面加载完
        //当el元素页面加载完,就调用
        axios.all([getdate(),getnumber(),getclientInfo()]).then(//方法在method中就要加this
            axios.spread( (d1,d2,d3) => {
	            /**
	              * 此处注意箭头函数与匿名函数的区别
	              * 箭头函数内部的this是词法作用域,在编写函数时就已经确定
	              * 匿名函数的this指向运行时实际调用该方法的对象,无法在编写函数时确定
	              */
                this.$data.time = d1.data.data;
                this.$data.userid = d2.data.data;
                this.$data.clientInfo = d3.data.data;
            })
        );
    },
});

function getdate() {//访问data,回送一个json字符串到页面上
    return axios.get("tools.action?op=date");
}
function getnumber() {
    var params = new URLSearchParams();
    params.append('op','number');
    return axios.post("tools.action",params);
}
function getclientInfo() {
    return axios.get("tools.action?op=clientInfo");
}

2.Java

private void date(HttpServletRequest request, HttpServletResponse response){
    Date date = new Date();
    Format format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
   
    JsonModel jsonModel = new JsonModel();
    try {
        jsonModel.setCode(1);
        jsonModel.setData(format.format(date));
        super.writeJson(jsonModel,response);
    } catch (IOException e) {
        e.printStackTrace();
        jsonModel.setCode(0);
        jsonModel.setMsg(e.getMessage());
    }
}

private void number(HttpServletRequest request, HttpServletResponse response){
    Random random = new Random();
    JsonModel jsonModel = new JsonModel();
    try {
        jsonModel.setCode(1);
        jsonModel.setData(random.nextInt(1000));
        super.writeJson(jsonModel,response);
    } catch (IOException e) {
        e.printStackTrace();
        jsonModel.setCode(0);
        jsonModel.setMsg(e.getMessage());
    }
}
    
private void clientInfo(HttpServletRequest request,HttpServletResponse response){
    JsonModel jsonModel = new JsonModel();
    try {
        jsonModel.setCode(1);
        String ip = request.getRemoteUser();
        String agent = request.getHeader("User-Agent");

        Map<String,String> data = new HashMap<String,String>();
        data.put("ip",ip);
        data.put("agent",agent);
        jsonModel.setData(data);
        super.writeJson(jsonModel,response);
    } catch (IOException e) {
        e.printStackTrace();
        jsonModel.setCode(0);
        jsonModel.setMsg(e.getMessage());
    }
}

super.writeJson---------------------------------------------------------------
protected void writeJson(JsonModel jm, HttpServletResponse response) throws IOException {
    //1.jm对象转成json字符串,第三方框架
    Gson gson = new Gson();
    String json = gson.toJson(jm);

    //2.通过responce将json字符串写到页面上
    response.setContentType("application/json;charset=utf-8");
    PrintWriter out = response.getWriter();
    out.println(json);
    out.close();
}