数据通信:
- ajax、跨域
- fetch
- jsonp
- Ajax2.0->FormData:直接提交表单,文件
- WebSocket
ajax:
- 原生
- jQuery
ajax为啥不能跨域?
- 原因:浏览器限制。ajax请求给浏览器,浏览器发送给服务器,服务器返回给浏览器,浏览器判断是否跨域,防止跨域服务器提供危险信息。
- 解决方法:服务器声明可跨域—origin、access-control-allow-origin
if(allowOrigin[origin]){
res.setHeader('access-control-allow-origin', '*');
}
SOP
fetch——原生、xhr
1.读取
2.解析
window.onload=function (){
let oBtn=document.getElementById('btn1');
oBtn.onclick=async function (){
//1.请求
let res=await fetch('data/1.txt');
//2.解析
let str=await res.text();
alert(str);
//1.请求
//let res=await fetch('data/1.json');
//2.解析
// let json=await res.json();
//alert(json);
//1.请求
// let res=await fetch('data/1.png');
//2.解析
//let data=await res.blob();
//let url=URL.createObjectURL(data);
// oImg.src=url;
};
};
jsonp:可跨域,不安全
- 1.原理
<script src="其他网站.js"></script>
function show({s}){
console.log(s);
}
window.onload=function (){
let oTxt=document.getElementById('txt1');
oTxt.oninput=function (){
let url=`https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=${this.value}&cb=show`;
let oS=document.createElement('script');
oS.src=url;
document.head.appendChild(oS);
};
};
<body>
<input type="text" id="txt1">
</body>
百度无法阻止跨域拿取数据,改接口名称5a1Fazu8AA54nxGko9WTAnF6hhy
- 2.jQuery
<script src="jquery.js" charset="utf-8"></script>
<script>
$(function (){
$('#txt1').on('input', function (){
$.ajax({
url: 'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
data: {wd: $(this).val()},
dataType: 'jsonp',
jsonp: 'cb'//不同网址定义的回调函数不同
}).then(({s})=>{
console.log(s);
}, res=>{
alert('失败');
});
});
});
</script>
</head>
<body>
<input type="text" id="txt1">
fetch
FormData:Ajax2.0的新特性
现在流行用表单,阻止原生表单提交,自己实现提交
- 1.原生实现提交
<body>
<form id="form1" action="http://localhost:8080/" method="post">
用户:<input type="text" name="user" /><br>
密码:<input type="password" name="pass" /><br>
文件:<input type="file" name="f1" /><br>
<input type="submit" value="提交">
</form>
</body>
<script>
let oForm=document.querySelector('#form1');
oForm.onsubmit=function (){
let formdata=new FormData(oForm);
let xhr=new XMLHttpRequest();
xhr.open(oForm.method, oForm.action, true);
xhr.send(formdata);
xhr.onreadystatechange=function (){
if(xhr.readyState==4){
if(xhr.status==200){
alert('成功');
}else{
alert('失败');
}
}
};
return false;//阻止表单自己提交
};
</script>
const http=require('http');
const multiparty=require('multiparty');
http.createServer((req, res)=>{
let form=new multiparty.Form({uploadDir: './upload/'});
form.parse(req);
form.on('field', (name, value)=>{
console.log('field:', name, value);
});
form.on('file', (name, file)=>{
console.log('file:', name, file);
});
form.on('close', ()=>{
console.log('完事');
});
}).listen(8080);
node server.js
field: user aaa
field: pass xxx
file: f1 { fieldName: 'f1',
originalFilename: '新建文本文档.txt',
path: 'upload\\laLlxTbWMYXezg-PdJ_ThTPP.txt',
headers:
{ 'content-disposition': 'form-data; name="f1"; filename="新建文本文档.txt"',
'content-type': 'text/plain' },
size: 49 }
完事
- jquery实现提交:自带处理formdata的方法
<body>
<form id="form1" action="http://localhost:8080/" method="post">
用户:<input type="text" name="user" /><br>
密码:<input type="password" name="pass" /><br>
文件:<input type="file" name="f1" /><br>
<input type="submit" value="提交">
</form>
</body>
<script src="jquery.js" charset="utf-8"></script>
<script>
$('#form1').on('submit', function (){
let formdata=new FormData(this);
$.ajax({
url: this.action,
type: this.method,
data: formdata,//jq会处理formdata
processData: false,//jq不要处理数据
contentType: false//不要改contentType
}).then(res=>{
alert('成功');
}, res=>{
alert('失败');
});
return false;
});
</script>
3.非表单:数据获取较麻烦,修改也麻烦,不推荐
<body>
<div id="div1">
用户:<input type="text" id="user" /><br>
密码:<input type="password" id="pass" /><br>
文件:<input type="file" id="f1" /><br>
<input id="btn1" type="button" value="提交">
</div>
</body>
<script>
let oBtn=document.querySelector('#btn1');
oBtn.onclick=function (){
let formdata=new FormData();
formdata.append('username', document.querySelector('#user').value);
formdata.append('password', document.querySelector('#pass').value);
formdata.append('f1', document.querySelector('#f1').files[0]);
let xhr=new XMLHttpRequest();
xhr.open('post', 'http://localhost:8080/', true);
xhr.send(formdata);
xhr.onreadystatechange=function (){
if(xhr.readyState==4){
if(xhr.status==200){
alert('成功');
}else{
alert('失败');
}
}
};
};
</script>
webSocket:
1.性能高
2.双向
-
1. socket.io
1.简单、方便
2.兼容 IE5
3.自动数据解析
服务器认证,断开自动重连
<script src="http://localhost:8080/socket.io/socket.io.js" charset="utf-8"></script>
<script>
let sock=io.connect('ws://localhost:8080/');
sock.emit('aaa', 12, 5);
sock.on('timer', time=>{
console.log(time);
});
//sock.emit
//sock.on
</script>
const http=require('http');
const io=require('socket.io');
//1.建立普通http
let server=http.createServer((req, res)=>{});
server.listen(8080);
//2.建立ws
let wsServer=io.listen(server);
wsServer.on('connection', sock=>{
//sock.emit('name', 数据)//发送数据
//sock.on('name', function (数据){});//接受数据
sock.on('aaa', function (a, b){
console.log(a, b, a+b);
});
setInterval(function (){
sock.emit('timer', new Date().getTime());
}, 1000);
});
$ node server
12 5 17
2.原生WebSocket
- 协议升级:握手
- 天然加密,比http安全
ws://
wss://
//握手建立连接的原生实现
const net=require('net');
const crypto=require('crypto');
function parseHeader(str){
let arr=str.split('\r\n').filter(line=>line);
arr.shift();
let headers={};
arr.forEach(line=>{
let [name, value]=line.split(':');
name=name.replace(/^\s+|\s+$/g, '').toLowerCase();//行首行尾去掉,变成小写
value=value.replace(/^\s+|\s+$/g, '');
headers[name]=value;
});
return headers;
}
let server=net.createServer(sock=>{
// on:有 once:一次
sock.once('data', buffer=>{
let str=buffer.toString();
// console.log(str);
let headers=parseHeader(str);
console.log(headers);
if(headers['upgrade']!='websocket'){
console.log('no upgrade');
sock.end();
}else if(headers['sec-websocket-version']!='13'){//基于版本13处理
console.log('no 13');
sock.end();
}else{
let key=headers['sec-websocket-key'];//http头里面来
let uuid='258EAFA5-E914-47DA-95CA-C5AB0DC85B11';//作者提供的 websocket258
let hash=crypto.createHash('sha1');//创建hash对象,签名是sha1
hash.update(key+uuid);//字符串连接
let key2=hash.digest('base64');//转成base64
//返回给客户端,版本 状态码101 头:升级的websocket 升级的连接 key2
sock.write(`HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection:upgrade\r\nSec-Websocket-Accept:${key2}\r\n\r\n`);
}
});
sock.on('end', ()=>{
});
});
server.listen(8080);
<script>
let ws=new WebSocket('ws://localhost:8080/');
ws.onopen=function (){
alert('连接已建立');
};
ws.onmessage=function (){};
ws.onclose=function (){};
ws.onerror=function (){};
</script>
network
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Key: VVrcCqPlD9Tw59SOzLRXsw== //测试
Sec-WebSocket-Version: 13
Upgrade: websocket
key=>http的头里来
uuid=>'258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
result=>base64(sha1(key+uuid))
101返回客户端成功
pending 一直连接着
网友评论