ajax
客户端的数据配置解析
搭建一个最简单的服务器
var http = require("http");
http.createServer(function(req,res){
res.writeHead(200, {
"Content-Type": "text/html;charset=utf-8",
"Access-Control-Allow-Origin": "*" //CORS 允许谁跨域访问
})
res.end("ok")
}).listen(3000,"10.9.46.184",function(){
console.log("服务器已开启");
})
创建一个最简单的ajax服务请求
var xhr = new XMLHttpRequest();
xhr.addEventListener("load",loadHandler);
xhr.open("POST","http://10.9.46.184:3000");
xhr.send("hdh");
function loadHandler(e){
console.log(xhr.response);
}
function Ajax(data){
return new Promise((resolve,reject)=>{
xhr = new XMLHttpRequest();
xhr.open("POST","http://localhost:3000");
xhr.send(data);
xhr.onload = function(){
resolve(xhr.response)
}
})
}
解析在ajax的open方法中的参数
xhr.open(Method,URL,async,user,password)
参数:Method:请求方法
- GET:
- POST
GET:重点在于我接收服务端的信息
POST:重点在于我客户端发送到服务器数据
GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark(记录),而POST不可以。
GET请求会被浏览器主动cache(缓存),而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST么有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。 GET产生一个TCP数据包;POST产生两个TCP数据包。
并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
- PUT
- DELETE
不需要考虑跨域问题,但是用这两个来访问服务器就得,考虑方法跨域问题。
提示服务端我给什么方式发送
遇到PUT和DELETE,
必须给响应头增加Access-Control-Allow-Methods:*
参数:URL请求路径
http:// 协议
localhost 域名
:4001 端口号
(/new/inded.html /new 路由/new/index.html 路径) ?a=1&b=2 search
#ab hash
在ajax请求中path 向node请求时一般不带有文件名,路径就是ajax请求的路由
如果在单页面开发时,#ab这种hash也叫做当前页面的路由
如果有路由里面有汉字字符信息,服务器解析路由会出现乱码,这是因为 URI 编码格式,现在浏览器一般都会自动将非法字符转换为这种编码,那么就需要
decodeURIComponent(); 将URI编码格式解析转换为中文
encodeURIComponent(); 将中文转换为URI编码格式
xhr.open("GET","http://10.9.46.184:3000/hello你好");
/hello%E4%BD%A0%E5%A5%BD
可在node中使用decodeURIComponent(req.url)解析
/hello你好
===========================================================
console.log(req.url);
console.log(decodeURIComponent(req.url));
console.log(encodeURIComponent(req.url));
/hello%E4%BD%A0%E5%A5%BD
/hello你好
%2Fhello%25E4%25BD%25A0%25E5%25A5%25BD
参数:async是否同步异步 ,默认是true,异步
默认true,是异步执行,通过侦听事件处理通信后的数据
如果修改false,是同步,但是这样会造成页面白屏
禁止使用,
参数user,password
user和password 当访问某个网站时,需要用户名和密码就需要在这里传入
知识点:
当在open中使用GET时,如果地址中使用了文件名,意味着加载这个文件,而不是和某个服务通信
这样我们完成了加载,这个加载就是加载配置文件
var xhr=new XMLHttpRequest();
xhr.addEventListener("load",loadHandler);
xhr.open("GET","http://localhost:5500/ajax/a.json");
xhr.send();
function loadHandler(e){
// console.log(JSON.parse(xhr.response))
//文本长度
console.log(xhr.response.length)
}
如果ajax同时发送两个,第一个就无效了
相同数据json格式比text文本格式的长度要长
xml的文本格式,虽然灵活所有语言支持其操作,但是数据冗余更大
var arr=Array.from(xhr.responseXML.querySelectorAll("man")).filter(item=>item.getAttribute("age")>23);
arr.forEach(item=>console.log(item))
//可以对他进行任何节点操作
服务端的接收数据的解析
方法 | 功能 |
---|---|
req.method |
客户端请求方式 |
put,delete | 会多请求一次服务器OPTIONS |
客户端请求头和服务器响应头
请求头必须在open之后,send之前设置
xhr.setRequestHeader(请求头KEY,请求头值)
如果自定义请求头信息或者不是在默认的修改请求头信息时,在跨域时必须在响应头中有设置
"Access-Control-Allow-Headers":"*"
允许头部跨域
这样设置后服务器中才可以获取到请求头提交的数据
自定义请求头时,我们希望大家以X起头使用-区分
例如:X-Name niuniu
可以通过设置Set-Cookie将cookie信息主动发送到服务端,这样就可以解决因为跨域造成cookie无法发送的问题
'content-length'
在POST发送数据时,会自动发送一个content-length,告知服务器,当前send发送的数据的长度,这个长度就是buffer数据流的长度。
function getData(req){
return new Promise(function(resolve,reject){
data=''
req.on("data",(_chunk)=>{
console.log(_chunk);
//<Buffer 68 64 68 e4 bd a0 e5 a5 bd>
data +=_chunk});
req.on("end",()=>{resolve(data)})
})
}
WriteHead
所有的响应数据使用同一个响应头
setHeader
可以根据不同的请求头设置不同的响应头
但是跨域的响应体内容就不会发送到客户端
这种方式,每次只能写入一个响应头,但是可以写入多个
而且使用SetHeader使用时必须写在WriteHead之前,在WriteHead之后不能使用SetHeader
res.setHeader("Access-Control-Allow-Origin","*")
如果自定义的响应头,需要在客户端获取,就需要设置 "Access-Control-Expose-Headers":["X-Name"]
也就是说这个服务器响应头内容,在客户通过 console.log(xhr.getAllResponseHeaders());//获取所有的响应头
这段代码拿到的只有是:
res.writeHead(200, {
"Content-Type": "text/html;charset=utf-8",
"Access-Control-Allow-Origin": "*", //CORS 允许谁跨域访问
// "Access-Control-Allow-Methods":"*"
"Access-Control-Allow-Headers": "*",
"X-Name": "xietian",
// "X-Set-Cookie": encodeURIComponent(str),
"X-Set-Cookie": "a=1",
"Access-Control-Expose-Headers": ["X-Name", "X-Set-Cookie"]
})
content-type: text/html;charset=utf-8
x-name: xietian
x-set-cookie: a=1
设置超时
var xhr=new XMLHttpRequest();
// 超时事件
xhr.addEventListener("timeout",timeoutHandler);
xhr.open("GET","http://localhost:4001");
xhr.timeout=2;//设置超时
xhr.send();
function timeoutHandler(e){
console.log("超时")
xhr.abort();//断开连接
// 超时重新发送
xhr.open("GET","http://localhost:4001");
xhr.send();
}
加载进度
var xhr=new XMLHttpRequest();
xhr.addEventListener("progress",progresshandler)
xhr.open("GET","http://localhost:5500/ajax/img/a.jpg");
xhr.send();
function progresshandler(e){
console.log(e);
// e.loaded: 364 已加载字节
// e.total: 364 总字节
console.log((e.loaded/e.total*100).toFixed(2)+"%");
}
xhr状态事件
var xhr=new XMLHttpRequest();
xhr.addEventListener("readystatechange",loadHandler);
xhr.addEventListener("error",errHandler);
xhr.open("GET","http://localhost:4001");
xhr.send();
function loadHandler(e){
console.log(xhr.status,xhr.readyState);
//xhr.readyState 当前ajax执行的进度
if(xhr.readyState===4 && xhr.status===200){
console.log(xhr.response)
}else if(xhr.readyState===4){
}
//当响应头接收时
if(xhr.readyState===2){
console.log(xhr.getAllResponseHeaders());
}
//向服务器发送的地址,其中包含参数和hash
console.log(xhr.responseURL)
}
function errHandler(e){
}
使用fetch
init();
async function init(){
var res=await fetch("http://localhost:4001",{
method:"POST",
body:"aa",
headers:{
"Content-Type":"appliction/x-www-form-encoded"
}
})
console.log(res)
console.log(res.headers);//获取响应头
for(var [key,value] of res.headers){
console.log(key,value)
}
解析服务端响应的文本数据
console.log(await res.text())
解析服务端响应的json数据
SyntaxError: Unexpected token a in JSON at position 0 当前的数据不符合json格式
console.log(await res.json())
}
把ajax封装成fetch方式
function ajax(url,{method="get",body,headers}={method:"GET"}){
return new Promise(function(resolve,reject){
var xhr=new XMLHttpRequest();
xhr.open(method,url);
if(headers){
for(var key in headers){
xhr.setRequestHeader(key,headers[key]);
}
}
body ? xhr.send(body) : xhr.send();
xhr.onreadystatechange=function(){
if(xhr.status===200 && xhr.readyState===4){
resolve(xhr.response);
}else if(xhr.readyState===4){
reject(xhr.status);
}
}
xhr.onerror=function(){
reject(xhr.responseURL+"通信地址错误")
}
})
}
init();
async function init(){
var res=await ajax("http://localhost:4001",{
method:"post",
body:"aaa"
})
}