美文网首页
nodejs基础3-数据通信:fetch,ajax2.0和web

nodejs基础3-数据通信:fetch,ajax2.0和web

作者: 栗子daisy | 来源:发表于2019-04-21 21:25 被阅读0次

数据通信:

  • 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 }
完事
    1. 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 一直连接着

相关文章

网友评论

      本文标题:nodejs基础3-数据通信:fetch,ajax2.0和web

      本文链接:https://www.haomeiwen.com/subject/qoilgqtx.html