AJAX
Async JavaScript And XML:异步的JS+XML
请求回顾
|
|
发请求的方法
地址栏回车
发起特定类型的请求:
图片发起请求:
<img src=/xxx>
请求头里:Accept: image/webp,image/,/* 期待接收图片
js发请求:
<script src=/xxx
请求头里:Accept:test/javascript, */*
css发请求:
<link rel=stylesheet href=/xxx>
请求头里:Accept:test/css,*/*
form表单发起请求:
<form action='/xxx' method=GET
(Accept:*/*)
缺点:1、3请求方法会刷新页面并替换当前页面内容,2请求方法只能请求特定类型资源
局部更新
要求:发一个请求,这个请求去更新页面里的局部内容,而不刷新整个页面。
js改变地址栏(更新了整个页面,不符合要求)
123456789前端:<button id="button">click</button><div>空的</div><script>button.onclick=function(){location.href = '/xxx'}</script>123456789101112131415161718192021222324252627282930313233服务器端:var http = require('http')var fs = require('fs')var url = require('url')//console.log(Object.keys(http))var port = process.env.PORT || 8888;var server = http.createServer(function(request, response){var temp = url.parse(request.url, true)var path = temp.pathnamevar query = temp.queryvar method = request.method//从这里开始看,上面不要看if(path === '/'){ // 如果用户请求的是 / 路径var string = fs.readFileSync('./index.html')response.setHeader('Content-Type', 'text/html;charset=utf-8')response.end(string)}else{response.statusCode = 404response.setHeader('Content-Type', 'text/html;charset=utf-8')response.end('找不到对应的路径,你需要自行修改 index.js')}// 代码结束,下面不要看console.log(method + ' ' + request.url)})server.listen(port)console.log('监听 ' + port + ' 成功,请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)
发一个图片请求(可以局部发请求,但是无法获取响应的数据内容,不符合要求)
12345678910前端:<button id="button">click</button><div>空的</div><script>button.onclick=function(){var img = new Image()img.src = '/xxx'}</script>1234567服务器端:......if(path === '/xxx'){response.end('这是xxx的内容')}else{response.end('404')}CSS发请求(同样的,无法拿到响应中的内容)
123456789101112131415161718前端:<body><button id="button">click</button><div>空的</div><script>button.onclick=function(){var link = document.createElement('link')link.rel='stylesheet'link.href='/xxx'link.onload = ()=>{console.log('link.innerHTML')console.log(link.innerHTML) //无法打印出里面的响应内容}document.head.appendChild(link)}</script></body>JS发请求
1234567891011<body><button id="button">click</button><div id="output">空的</div><script>button.onclick=function(){var script = document.createElement('script')script.src = '/xxx'document.head.appendChild(script)}</script>报错:js请求的路径是’/xxx’,那么路径对应的内容因该是合法的js字符串;而我们返回的是’here is xxx’字符串,所以报错。(但是浏览器把它当成js解析了,这是转机)
修改路径内容,使之能被js那样被解析
1234if(path === '/xxx'){response.setHeader('Content-Type','text/plain;charset=utf-8')response.end('output.innerText="here is xxx"')//或者一个随机数response.end(`output.innerText=${Math.random()}`)- 1234567891011前端:<script>window.callback = function(){console.log(arguments[0]) //打出第一个参数}button.onclick=function(){var script = document.createElement('script')script.src = '/xxx'document.head.appendChild(script)}</script>12345服务器端:if(path === '/xxx'){response.setHeader('Content-Type','text/plain;charset=utf-8')var user = 'name:tom,age:18'response.end(`window.callback.call(null,"${user}")`)
变换
1234567891011121314151617181920212223242526前端:<body><button id="button">click</button><div id="output">空的</div><script>window.callback = function(data){var array = data.split(',') //["name: tom "," age: 18""] //字符串转成数组for(var i=0;i<array.length;i++){ //遍历数组var parts = array[i].split(":") //["name"," tom "]var dl = document.createElement("dl")var dt = document.createElement('dt')dt.textContent = parts[0]var dd = document.createElement('dd')dd.textContent = parts[1]dl.appendChild(dt)dt.appendChild(dd)output.appendChild(dl)}}button.onclick=function(){var script = document.createElement('script')script.src = '/xxx'document.head.appendChild(script)}</script>12345服务器端:else if(path === '/xxx'){response.setHeader('Content-Type','text/plain;charset=utf-8')var user = 'name: tom , age: 18'response.end(`window.callback("${user}")`)
总结:
- 发起请求:创造一个script放入页面,script请求一个路径
- 服务器响应:回调一个函数,这个函数对参数(数据)进行处理分解,构造成有结构的html页面
检测请求是否正确
前端:onerror和onload
123456789//前端出错:可以用onerror来提示:status只要不是2xx就触发onerrorbutton.onclick=function(){var script = document.createElement('script')script.onerror = ()=>{alert('不好意思,出错了')}script.src = '/xxxx' //请求路径出错document.head.appendChild(script)}123456789后端出错:可以用onload来提示前端请求没问题;只要status是2xx,就触发onloadbutton.onclick=function(){var script = document.createElement('script')script.onload = ()=>{alert('请求没问题,后端出错了')}script.src = '/xxxx' //请求路径出错document.head.appendChild(script)}局限性:不知道具体哪里错误,不知道错误码。
XHMHttpRequest
XMLHttpRequest 是一个API, 它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。
- 在不重新加载页面的情况下更新网页
- 在页面已加载后从服务器请求数据
- 在页面已加载后从服务器接收数据
- 在后台向服务器发送数据
- 前身:微软的ActiveX对象,提供给ie的接口(帮你发请求,并且把请求的响应用字符串的形式响应 给你)
- 火狐跟进:XMLHttpRequest ,用这个对象发请求,并得到响应,并且不会对整个页面刷新。
实例化:
var request = new XMLHttpRequest()
方法:
- abort():如果请求已经被发送,则立刻终止请求
- getAllResponseHeaders():返回所有响应头信息(响应头名和值)
- getResponseHeader():返回指定的响应头的值
请求:
请求行 - open(method,ulr,async):
request.open('GET' , '/xxx?wd=s',true)
(查询字符串写在url里)请求头 - setRequestHeader(header,value):
setRequestHeader('tom','18')
消息体 - send():发送请求
send('44444')
- 12345678<script>button.onclick = ()=>{var request = new XMLHttpRequest()request.open('POST','/xxx?aa=b')request.setRequestHeader('tom','18')request.send('sfsdf')}</script>
响应:
- 获取响应头:request.getAllResponseHeaders()
1234567891011121314<script>button.onclick = ()=>{var request = new XMLHttpRequest()request.open('POST','/xx x?aa=b')request.setRequestHeader('tom','18')request.send('sfsdf')request.onload = ()=>{console.log(request.getAllResponseHeaders())}request.onerror = ()=>{console.log(request.getAllResponseHeaders())}}</script>获取响应消息体(第四部分):request.responseText / window.eval(request.responseText)
12345678910111213<script>button.onclick = ()=>{var request = new XMLHttpRequest()request.open('POST','/xxx?aa=b')request.setRequestHeader('tom','18')request.send('sfsdf')request.onload = ()=>{console.log(request.responseText) //打印出来文本window.eval(request.responseText) //eval可以执行字符串,即执行了响应的第四部分}}</script>获取响应第一部分:状态行
12状态码 request.status //200状态码描述 request.statusText //OK
精确检查响应的状态:onreadystatechange ,只要readyState变化,这个函数就会被调用
123456789101112request.onreadystatechange = function(){console.log(request.readyState) //01234个值if(request.readyStatus === 4){ //响应下载完毕if(request.status >=200 && request.status <300){console.log('成功')}else{console.log('失败')}}}//request.onload //响应下载完毕,而且status是2XX//request.onerror //1.响应出错(未发出、 网络等),2.下载完毕但是status是4xx 5xxx
小结
ajax总共有4个过程 ,
创建ajax对象:
const ajax = new XMLHttpRequest()
连接到服务器:
ajax.open(method,url,async)
发送请求:
ajax.send()
接收返回的信息:
12345678ajax.onreadystatechange=function(){ajax.readyState//0 未初始化,还没调用open方法//1 载入,已经调用send()方法,正在发送请求//2 载入完成,send()方法完成,已经收到全部相应内容//3 解析,正在解析响应内容//4(普遍是4) 完成,响应内容完成解析(可能成功,可能失败,用ajax.status来判断。成功时候可以用ajax.responseText来获取响应的内容}