Ajax总结

一、Ajax简介

1.Ajax相关

AJAX 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML。

通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。

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

2.XML相关

XML 可扩展标记语言。

XML 被设计用来传输和存储数据。

XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据。

例如一个学生数据:name = "孙悟空" ; age = 18 ; gender = "男" ;

用XML表示:

    <student>
        <name>孙悟空</name>
        <age>18</age>
        <gender>男</gender>
    </student>

用JSON表示:{"name":"孙悟空","age":18,"gender":"男"}

如今XML已经被JSON取代了

3.Ajax的工作原理

Ajax的工作原理相当于在用户和服务器之间加了一个中间层(Ajax引擎),使用户操作与服务器响应异步化。

4.Ajax的特点
  • 优点
    可以无需刷新页面而与服务器端进行通信。
    允许你根据用户事件来更新部分页面内容。
  • 缺点
    没有浏览历史,不能回退
    存在跨域问题
    SEO不友好

二、原生Ajax

1.原生Ajax发送get请求

步骤:

  • 实例化一个XMLHttpRequest对象
    XMLHttpRequest是核心对象,Ajax的所有操作都是通过该对象进行的。

  • 给对象绑定一个事件监听

    在xhr内部有五种状态

    • 0:当xhr被实例化出来,状态就是0,即初始化状态
    • 1:请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头
    • 2:请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了
    • 3:数据回来了,但是数据可能不完整,如果数据小,会在此阶段直接接受完毕,数据大则有待于进一步接受
    • 4:数据完全回来了
  • 指定发送请求的方式,地址,参数

  • 发送请求

    btn.onclick=function(){
        //1.实例化一个XMLHttpRequest对象
        const xhr=new XMLHttpRequest();
        //2.给对象绑定一个事件监听
        xhr.onreadystatechange=function(){
            if(xhr.readyState===4&&xhr.status===200){
                console.log(xhr.response);
                let demo=document.getElementById("demo");
                demo.innerHTML=xhr.response;
            }
        };
        //3.指定发送请求的方式,地址,参数
        xhr.open("GET","http://localhost:3000/test_get?name=dexter&&age=20");
        //4.发送请求
        xhr.send();
    };

对于readyState状态码的说明
一般不会在0,1,2,3这几种状态的回调中,做任何逻辑

    const xhr=new XMLHttpRequest();
    if(xhr.readyState===0){
        console.log("我出生了");
    }
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 1) {
            xhr.setRequestHeader("demo", 123);
            console.log("请求还没有发出去,即:send方法还没有被调用,依然可以修改请求头");
        }
        if (xhr.readyState === 2) {
            //如果在这里修改请求头会报错
            console.log("请求已经发出去了,即:send方法已经被调用了,不能再修改请求头,响应首行和响应头已经回来了");
            console.log(xhr.getResponseHeader("Date"));//Wed, 14 Oct 2020 12:28:58 GMT
        }
        if (xhr.readyState === 3) {
            console.log("数据回来了,但是数据可能不完整,如果数据小,会在此阶段直接接受完毕,数据大则有待于进一步接受");
            console.log(xhr.response);//get请求发回的数据
        }
        if (xhr.readyState === 4) {
            console.log("数据完全回来了");
        }
    };
2.原生Ajax发送post请求

步骤

  • 实例化一个XMLHttpRequest对象
  • 给对象绑定一个事件监听
  • 指定发送请求的方式,地址,参数
  • 设置post请求所特有的请求头
  • 发送请求
    btn.onclick=function(){
        //1.实例化一个XMLHttpRequest对象
        const xhr=new XMLHttpRequest();
        //2.给对象绑定一个事件监听
        xhr.onreadystatechange=function(){
            if(xhr.readyState===4&&xhr.status===200){
                console.log(xhr.response);
                let demo=document.getElementById("demo");
                demo.innerHTML=xhr.response;
            }
        };
        //3.指定发送请求的方式,地址,参数
        xhr.open("POST","http://localhost:3000/test_post");
        //4.设置post请求所特有的请求头
        xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
        //5.发送请求
        xhr.send("name=dexter&&age=20");
    };

post请求与get请求的区别是post请求需要设置特殊的请求头,在发送数据时是在send中发送而get请求则是以urlencoded编码形式发送。

3.IE中存在的问题

对于chrome和火狐来说,当请求地址不发生变化时,浏览器会尝试走协商缓存。但是对于IE只要请求的地址不发生变化,会直接走强缓存,这样会导致服务端修改了代码但是浏览器刷新不出来效果的情况。因此在开发中为了应对IE的强缓存,会在请求参数中加一个无关的时间戳参数。

    const xhr=new XMLHttpRequest();
    xhr.onreadystatechange=function(){
        if(xhr.readyState===4&&xhr.status===200){
            console.log(xhr.response);
            let demo=document.getElementById("demo");
            demo.innerHTML=xhr.response;
        }
    };
    xhr.open("GET","http://localhost:3000/test_get?name=dexter&age=20&t="+Date.now());
    xhr.send();
4.使用promise封装原生Ajax
  • 定义发送Ajax发送请求的模板函数
    function sendAjax(url,method,data){
        return new Promise((resolve,reject)=>{
            //1.创建xhr对象
            let xhr=new XMLHttpRequest();
            //2.绑定监听
            xhr.onreadystatechange=function(){
                if(xhr.readyState!==4){
                    return
                }
                if(xhr.readyState===4&&(xhr.status>=200&&xhr.status<300)){
                    const responseObj={
                        data:xhr.response,
                        status:xhr.status,
                        statusText:xhr.statusText
                    };
                    resolve(responseObj);
                }else{
                    reject(new Error("请求出错了"));
                }
            };
            //3.将传递过来的数据加工成urlencoded形式的编码
            let dataKeys=Object.keys(data);//将对象的键封装成数组的形式
            /* Array(3)
                0: "m"
                1: "n"
                2: "r"
                length: 3 */
            let str=dataKeys.reduce(function(pre,now){
                return pre+=`${now}=${data[now]}&`;
            },""); //m=1&n=2&r=4&
            //4.发送请求
            if(method.toLowerCase()==="get"){
                url+=`?${str}`;
                xhr.open(method,url);
                xhr.send();
            }else if(method.toLowerCase()==="post"){
                xhr.open(method,url);
                xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
                xhr.send(str);
            }
        })
    }
  • 发送get请求
    obj1={
        m:1,
        n:2,
        r:4
    };
    btn1.onclick=function(){
        sendAjax("http://localhost:3000/test_get","GET",obj1).then((data)=>{
            console.log(data);
        }).catch((err)=>{
            console.log(err);
        })
    };
  • 发送post请求
    obj2={
        name:"dexter",
        age:25
    }
    btn2.onclick=function(){
        sendAjax("http://localhost:3000/test_post","POST",obj2).then((data)=>{
            console.log(data);
        }).catch((err)=>{
            console.log(err);
        })
    };
5.服务端代码
    const { request, response } = require("express");
    let express=require("express");
    let app=express();

    //暴露静态资源
    app.use(express.static(__dirname+"/public"));
    //解析psot请求请求体中的urlencoded形式的参数
    app.use(express.urlencoded({extended:true}));

    app.get("/test_get",(request,response)=>{
        console.log("一个get请求来了",request.query);
        response.send("get请求发回的数据");
    })
    app.post("/test_post",(request,response)=>{
        console.log(request.body);
        console.log("一个post请求来了");
        response.send("post请求发回的数据");
    })

    app.listen(3000,(err)=>{
        if(!err){
            console.log("服务器已启动,3000端口正在监听");
        }else{
            console.log(err);
        }
    })

三、取消上一次请求

问题描述:
当用户点击鼠标发送一次请求在没有得到服务器响应之前再次点击了请求,或者连续多次发送请求,这样会导致服务器在反映过来后向用户多次返回相同的数据,造成用户体验较差。因此应当对这样的情况进行处理,即当用户连续多次的发送同样的请求时即使服务器当下处理不过来,在反应过来时也只给用户返回最后一次请求的数据。

    let lastxhr
    btn.onclick = function () {
        if (lastxhr) {
            lastxhr.abort();
            /* abort()的工作方式
            当用户点击的速度一般时,abort会追回用户的请求,服务器不会接收到用户的请求
            当用户点击的速度非常快时以至于abort追不上时,abort会拦截服务器返回的数据 */
        }
        lastxhr = getcode();
    };
    function getcode() {
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && (xhr.status >= 200 && xhr.status < 300)) {
                console.log(xhr.response);
            }
        };
        xhr.open("GET", "http://localhost:3000/get_code");
        xhr.send();
        return xhr;
    }

服务端代码

    app.get("/get_code",(request,response)=>{
        //返回一个1000-9999的数
        console.log("页面请求验证码");
        let code=Math.floor(Math.random()*8999+1000);
        setTimeout(()=>{
            response.send(code.toString());//如果返回一个纯数字服务器会以为返回的是状态码而报错
        },2000)
        
    })

四、使用jQuery封装Ajax

1.jQuery发送get请求
  • 完整写法中常用的几个参数

    --method: 发送请求的方式
    --data: 要传递的数据
    --success: 成功的回调
    --error: 失败的回调

    let btn1 = $("#btn1");
    btn1.click(function () {
        $.ajax("http://localhost:3000/test_get",{
            method:"GET",
            data:{
                name:"dexter",
                age:25
            },
            success:function(result){
                console.log(result);
            },
            error:function(err){
                console.log(err);
            }
        })
    })
  • 精简写法的参数

    精简的写法直接传入请求地址和请求参数以及一个回调函数
    这个回调函数会有三个形参:
    第一个形参表示返回来的数据
    第二个参数表示当前请求的状态
    第三个参数是内部使用的xhr对象
    但是一般在使用时只传进去一个参数,即服务器返回来的数据

    $.get("http://localhost:3000/test_get", { name: "dexter", age: 25 }, (data) => {
        console.log(data);
    })
2.jQuery发送post请求
  • 完整写法
    btn2.click(function () {
        $.ajax("http://localhost:3000/test_post",{
            method:"POST",
            data:{
                name:"dexter",
                age:25
            },
            success:function(result){
                console.log(result);
            },
            error:function(err){
                console.log(err);
            }
        })
    })
  • 精简写法
    $.post("http://localhost:3000/test_post", { name: "dexter", age: 25 }, (data) => {
        console.log(data);
    })
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,753评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,668评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,090评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,010评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,054评论 6 395
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,806评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,484评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,380评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,873评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,021评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,158评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,838评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,499评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,044评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,159评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,449评论 3 374
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,136评论 2 356

推荐阅读更多精彩内容

  • 原文出处 http://blog.poetries.top/2016/11/26/Ajax-summary 关注公...
    程序员poetry阅读 6,692评论 3 110
  • 本文主要总结整理Ajax的一些常用的基础知识,适合初学者。 一、Ajax简介、优劣势、应用场景以及技术 Ajax简...
    Aniugel阅读 599评论 0 1
  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 X...
    fenerchen阅读 555评论 0 2
  • 18.3.23·AJAX概念简述、内部实现原理 ·常用方法:load()、$.get()、$.post()、$.g...
    静心安分读书阅读 248评论 0 3
  • Ajax 什么是Ajax Ajax = 异步 JavaScript 和 XML。 AJAX 是一种用于创建快速动态...
    有你不苦_阅读 395评论 0 2