博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AJAX
阅读量:6275 次
发布时间:2019-06-22

本文共 13876 字,大约阅读时间需要 46 分钟。

可以如何发送请求

  • <form>可以发请求,但是会刷新页面或新开页面

  • <a>只可以发 get 请求,但是也会刷新页面或新开页面
  • <img>只可以发 get 请求,但是只能以图片的形式展示
  • <link>只可以发 get 请求,但是只能以 CSS、favicon 的形式展示
  • <script>只可以发 get 请求,但是只能以脚本的形式运行

❓有没有什么方式可以实现:get、post、put、delete 请求都行,想以什么形式展示就以什么形式展示❓

ajax

Asynchronous Javascript And XML

异步 Javascript 和 XML

需要满足下面三个条件,可以称之为 ajax:

  1. 使用 XMLHttpRequest 发请求
  2. 服务器返回 XML 格式的字符串
  3. JS 解析 XML,并更新局部页面

不过随着技术发展,XML 越来越不常用,经常使用 JSON 代替 XML

version1.0

我们尝试做一个按钮,点击向服务器发送一个请求

html :

    
ajax_html

main.js :

myButton.addEventListener=('click',function(e){    var request= new XMLHttpRequest();         //新建请求    request.onreadystatuschange=function(){    //当请求的状态有变化时,打印出状态码        console.log(request.readyStatus);    }    request.open('GET','/xxx');                //初始化,GET 方法,/xxx 路径    request.send();                            //发送请求})

后端代码 :

}else if(path==='/xxx'){    response.statusCode = 200    response.setHeader('Content-Type', 'text/xml;charset=utf-8')    response.write(`        //xml        
Tove
Jani
Reminder
Don't forget me this weekend!
`) response.end()}

效果 :

当点击 点我 按钮时,首先,新建一个XMLHttpRequest请求;其次,使用 GET 方法请求到 /xxx;最后,发送请求。

当服务器收到请求了 /xxx 路径,然后,就返回了一串格式符合 XML字符串

并且,当请求和响应进行到各个状态时,都会打印出它的状态码

(状态码请参考:)
返回xml

version2.0-获取xml

除了可以获取状态码、在浏览器控制台获取服务器返回的XML字符串外,还可以将XML字符串转换为XML

并且可以使用DOM获取元素的API,来获取XML的元素,例如getElementByTagNames...
修改后的 main.js 如下所示,新增内容和注释如??所指。

main.js :

myButton.addEventListener=('click',function(e){    var request= new XMLHttpRequest();         //新建请求    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         ?//表示请求响应都已经完成            if(request.status === 200){        ?//表示服务器返回成功                ?//下面三句 let 用来获取返回的 xml,而不再是之前字符串格式                let parser = new DOMParser();                ?//返回的内容可以用 responseText 获取                let xmlDoc = parser.parseFromString(request.responseText,'text/xml');                let title = xmlDoc.getElementsByTagNames('heading')[0].textContent;            }        }    }    request.open('GET','/xxx');                //初始化,GET 方法,/xxx 路径    request.send();                            //发送请求})

version3.0-JSON

由于 xml 看上去不够简洁,而且实际使用中,获取的方式比较繁琐(参考上面的三句 let),所以,发明了一个新的数据格式化语言——JSON,用以替代 xml。

(JSON参考官网:)

JSON vs. Javascript:

  1. 没有 functionundefined
  2. 字符串首尾必须是双引号 ""
  3. 没有 变量
  4. 没有 原型链

修改后端代码,使其返回一个JSON,??为修改处。

后端代码 :

}else if(path==='/xxx'){    response.statusCode = 200    response.setHeader('Content-Type', 'text/json;charset=utf-8')    //?xml修改成json    response.write(`        //json            //??返回json而不是xml        {            "note":{                "to":"Tove",                "from":"Jani",                "heading":"Reminder",                "body":"Don`t forget me this weekend!"            }        }    `)    response.end()}

由于服务器返回的只能是一个字符串(响应第4部分只能是字符串),所以,我们也需要将返回的JSON字符串转换为一个对象,方便操作。

接下来,可以使用js对对象的操作,获取json的内容。

修改后的前端代码,?为修改处。

main.js :

myButton.addEventListener=('click',function(e){    var request= new XMLHttpRequest();         //新建请求    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         //表示请求响应都已经完成            if(request.status === 200){        //表示服务器返回成功                console.log("请求成功");                let string=request.responseText;            ?//获取服务器返回的字符串                let jsonObject=window.JSON.parse(string);   ?//将返回的字符串变成对象                console.log(jsonObject.note);               ?//输出对象里的note                console.log(jsonObject.note.from);          ?//输出对象里的note里的from            }        }    }    request.open('GET','/xxx');                //初始化,GET 方法,/xxx 路径    request.send();                            //发送请求})

同源策略&CORS跨域

<form>表单提交内容不一样,AJAX不刷新页面,并且可以读取响应内容,所以被浏览器认为是不安全的,

所以:

只有 协议+域名+端口 一模一样的时候,才允许发送AJAX请求

Σ(っ °Д °;)っ

那要是我必须需要另一个网站的接口怎么办???

如果http://www.kitty.com想要访问http://www.ben.com的一个接口,那Ben只需要在后端代码里加上一句话,告诉浏览器,http://www.kitty.comhttp://www.ben.com是友好关系,可以互相访问。

Ben的后端代码:

}else if(path==='/xxx'){           //请求的接口    response.statusCode = 200      //返回状态码    response.setHeader('Content-Type', 'text/json;charset=utf-8')    //设置返回类型为json    ?//此句开启友好模式    response.setHeader('Access-Control-Allow-Origin', 'http://www.kitty.com')    response.write(`        //json        {            "note":{                "to":"Tove",                "from":"Jani",                "heading":"Reminder",                "body":"Don`t forget me this weekend!"            }        }    `)    response.end()}

添加response.setHeader('Access-Control-Allow-Origin', 'http://www.kitty.com'),浏览器就知道,Kitty和Ben是好朋友,可以互相访问啦!!!

上述方法称之为:

Cross-Origin Resource SharingCORS

使用Javascript发送任意格式的请求

AJAX还允许用户使用Javascript设置一个请求的任意部分,并且可以获取一个响应的任意部分。

一个请求:

GET /xxx HTTP/1.1    //第一部分,方法、地址、协议、协议版本号HOST:                //第二部分,包含很多行,包含很多内容Content-Type:        //第二部分,包含很多行,包含很多内容                     //第三部分,一个回车这里是请求体          //第四部分

一个响应:

Http/1.1 200 OK      //第一部分,协议、协议版本号、状态码、状态信息Content-Type:        //第二部分,                     //第三部分,一个回车这里是响应体          //第四部分

发送一个任意的请求&获取一个响应任意部分:

myButton.addEventListener=('click',function(e){    var request= new XMLHttpRequest();            //新建请求    request.open('GET','/xxx');                   //设置请求第一部分:方法、路径    request.setRequestHeader('Content-Type','x-www-form-urlencoded);    //设置请求第二部分    request.send('虽然我是GET,但我也有请求体');    //设置请求第四部分    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         //表示请求响应都已经完成            if(request.status === 200){        //表示服务器返回成功                console.log("请求成功");                console.log(request.status)        //获取响应第一部分,状态码                console.log(request.statusText)    //获取响应第一部分,状态信息                console.log(request.getResponseHeader('Content-Type'))    //获取响应第二部分                console.log(request.getAllResponseHeaders);      //获取所有响应第二部分                console.log(request.responseText);               //获取响应第四部分            }        }    }})

总结:

总之,就是AJAX允许用户使用Javascript设置任意一个请求(浏览器不让设置的内容不能设置),也能获取一个响应的任意部分。

使用 JS 设置任意请求 header

  • 第一部分:request.open('get','/xxx')
  • 第二部分:request.setHeader('Content-type','x-www-form-urlencoded')
  • 第四部分:request.send('a=1&b=2')

使用 JS 获取任意响应 header

  • 第一部分:request.status / request.statusText
  • 第二部分:request.getResponseHeader() / request.getAllResponseHeaders()
  • 第四部分:request.responseText

客户端与服务器

封装ajax

我们的目标是只使用一个函数,就能实现下面发送请求的功能:

  • request.open('GET','/xxx');
  • request.onreadystatuschange=function(){}
  • request.send('虽然我是GET,但我也有请求体');

version1.0

封装后的前端代码:

window.jquery=function(){}window.$=window.jquery;window.jquery.ajax=function(url,method,body,successFn,failFn){    var request = new XMLHttpRequest();            //新建请求    request.open(method,url);                     ?//传入发送请求方式、请求地址    request.send(body);                           ?//传入请求体    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         //表示请求响应都已经完成            if(request.status === 200){        //表示服务器返回成功                successFn.call(undefined,request.responseText);  ?//响应成功,调用传入的成功函数            }else if(request.status >= 400){                failFn.call(undefined,request);   ?//相应失败,调用传入的失败函数            }        }    }}myButton.addEventListener=('click',function(e){    window.jquery.ajax(        '/xxx',        'GET',        '虽然我是GET,但我也有请求体'        function(){},        function(){}    )})

实现的功能是一样的,只是将ajax封装在一个函数里,之后调用只需要调用一个函数,出入响应的参数就能实现发送请求的功能。

version2.0

上个版本封装的很好,但是有几个问题:

  • 需要传入的参数太多,可能是不是会忘了需要传入什么参数,无法快速的知道参数含义
  • 当有一个参数用户不想传入的时候,只能使用null进行占位,很麻烦

所以,我们想到,给它传入一个集成的参数,把需要的参数都放在一个对象里,这样可以给参数指定名字,调用时,可以调用对象里的名字。

修改封装后的前端代码:

window.jquery=function(){}window.$=window.jquery;window.jquery.ajax=function(option){    ?//由原来的传入一个个的参数,变为传入包含所有参数的对象    ?//首先获取参数对象里的各个值    let url=option.url;    let method=option.method;    let body=option.body;    let successFn=option.successFn;    let failFn=option.failFn;    var request = new XMLHttpRequest();            //新建请求    request.open(method,url);                      //传入发送请求方式、请求地址    request.send(body);                            //传入请求体    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         //表示请求响应都已经完成            if(request.status === 200){        //表示服务器返回成功                successFn.call(undefined,request.responseText);   //响应成功,调用传入的成功函数            }else if(request.status >= 400){                failFn.call(undefined,request);    //相应失败,调用传入的失败函数            }        }    }}myButton.addEventListener=('click',function(e){    window.jquery.ajax(        ?//由原来的传入一个个的参数,变成现在传入一个包含所有参数的对象        {            url: '/xxx',            method: 'GET',            body: '虽然我是GET,但我也有请求体'            successFn: function(){},            failFn: function(){}        }    )})

version3.0

我们还需要封装发送请求头:

再次修改封装后的前端代码:

window.jquery=function(){}window.$=window.jquery;window.jquery.ajax=function(option){    //由原来的传入一个个的参数,变为传入包含所有参数的对象    //首先获取参数对象里的各个值    let url=option.url;    let method=option.method;    let body=option.body;    let successFn=option.successFn;    let failFn=option.failFn;    let headers=option.headers;    ?//获取参数对象里的headers        ?//遍历headers,将里面的键、值都设置在请求头里    for(let key in headers){        let value=headers[key];        request.setRequestHeader(key,value);    }    var request = new XMLHttpRequest();            //新建请求    request.open(method,url);                      //传入发送请求方式、请求地址    request.send(body);                            //传入请求体    request.onreadystatuschange=function(){            console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码        if(request.readyStatus === 4){         //表示请求响应都已经完成            if(request.status === 200){        //表示服务器返回成功                successFn.call(undefined,request.responseText);   //响应成功,调用传入的成功函数            }else if(request.status >= 400){                failFn.call(undefined,request);    //相应失败,调用传入的失败函数            }        }    }}myButton.addEventListener=('click',function(e){    window.jquery.ajax(        ?//在参数对象里传入headers,里面包括了想要设置的请求头的键、值        {            url: '/xxx',            method: 'GET',            headers: {                'content-type': 'application/x-www-form-urlencoded',                'color': 'red'            }            body: '虽然我是GET,但我也有请求体'            successFn: function(){},            failFn: function(){}        }    )})

运用jQuery使用ajax

请参考jQuery文档:

jquery_ajax

题外话

计算代码执行时间

下列代码可以计算从console.time()console.timeEnd()之间代码执行的时间

console.time()    //your codeconsole.timeEnd()

结构化编程:

  • 顺序执行
  • if...else...
  • while/for

ES6解构赋值

使用ES6解构赋值新语法可以简化下列代码:

window.jquery.ajax=function(option){    let url=option.url;    let method=option.method;    let body=option.body;    let successFn=option.successFn;    let failFn=option.failFn;    let headers=option.headers;         //your code}

解构之后:

window.jquery.ajax=function(option){    let {url,method,body,successFn,failFn,headers}=option;        //your code}

更加高级点:

window.jquery.ajax=function({url,method,body,successFn,failFn,headers}){        //your code}

?直接从window.jquery.ajax=function(){}的第一个参数里解构,并用let声明!!!

version4.0-Promise

当用户要使用很多ajax的时候,用i定义的或者别人自定义的,这样,每个人ajax的接口名称都不一样,用起来很麻烦,这时候,我们可以使用Promise技术

使用Promise和then:

??为修改处

window.jquery=function(){}window.$=window.jquery;window.jquery.ajax=function({url,method,body,headers}){                                    ?//使用ES6解构新语法,并且删除了successFn、failFn                                    ?//promise和之后使用ajax时的then一起,可以自动判断成功函数和失败函数    return new Promise(function(resolve,reject){             //遍历headers,将里面的键、值都设置在请求头里        for(let key in headers){            let value=headers[key];            request.setRequestHeader(key,value);        }            var request = new XMLHttpRequest();            //新建请求        request.open(method,url);                      //传入发送请求方式、请求地址        request.send(body);                            //传入请求体        request.onreadystatuschange=function(){                console.log(request.readyStatus);      //当请求的状态有变化时,打印出状态码            if(request.readyStatus === 4){         //表示请求响应都已经完成                if(request.status === 200){        //表示服务器返回成功                    ?//响应成功,调用传入的成功函数,修改sucessFn为resolve                    resolve.call(undefined,request.responseText);                 }else if(request.status >= 400){                    ?//响应成功,调用传入的成功函数,修改failFn为reject                    reject.call(undefined,request);    //相应失败,调用传入的失败函数                }            }        }    })}myButton.addEventListener=('click',function(e){    window.jquery.ajax(        //在参数对象里传入headers,里面包括了想要设置的请求头的键、值        {            url: '/xxx',            method: 'GET',            headers: {                'content-type': 'application/x-www-form-urlencoded',                'color': 'red'            }            body: '虽然我是GET,但我也有请求体'        }    ).then(function(){},function(){})        ?//这就是promise,就是在ajax后面加上then,    ?//传入第一个函数会被当成是成功时调用的函数,第二个函数会被当成失败时调用的函数})

如果需要多次处理:

//your codemyButton.addEventListener=('click',function(e){    window.jquery.ajax(        //在参数对象里传入headers,里面包括了想要设置的请求头的键、值        {            url: '/xxx',            method: 'GET',            headers: {                'content-type': 'application/x-www-form-urlencoded',                'color': 'red'            }            body: '虽然我是GET,但我也有请求体'        }    ).then(        function(){            //your code            return xxx;        },        function(){})     .then(         function(){},         function(){})        ?//这就是promise,就是在ajax后面加上then,    ?//传入第一个函数会被当成是成功时调用的函数,第二个函数会被当成失败时调用的函数    ?//当需要多次调用,可以在then的函数里直接return,return的内容会被当成之后then的输入,直接处理})

转载地址:http://qagpa.baihongyu.com/

你可能感兴趣的文章
运维基础命令
查看>>
Linux下的lds链接脚本简介(二)
查看>>
入门到进阶React
查看>>
C++每日练笔之日期类(基类)
查看>>
SVN 命令笔记
查看>>
修复Postfix 的Relay access denied问题
查看>>
检验手机号码
查看>>
重叠(Overlapped)IO模型
查看>>
ffmpeg study 1
查看>>
Git使用教程
查看>>
使用shell脚本自动监控后台进程,并能自动重启
查看>>
Flex&Bison手册
查看>>
MySQL 5.6 for Windows 解压缩版配置安装
查看>>
solrCloud+tomcat+zookeeper集群配置
查看>>
/etc/fstab,/etc/mtab,和 /proc/mounts
查看>>
Apache kafka 简介
查看>>
socket通信Demo
查看>>
技术人员的焦虑
查看>>
js 判断整数
查看>>
建设网站应该考虑哪些因素
查看>>