node之HTTP 從服務端感覺ajax和form

ajax發送請求,須要傳輸數據,數據有不一樣的類型,因此也是靠請求頭告訴後臺處理邏輯javascript

傳輸數據的方式有不少種html

http: 1.0,1.1(keep-alive) 複用鏈接, 2.0 https 新特色雙向通訊,多路複用前端

數據交互的方式

客戶端主動發送請求給服務端,服務端返回數據,咱們叫單向通訊

  • 表單 (會頁面跳轉,若是是get會加個?,若是是post就會跳轉業面,頁面從新渲染,從新請求服務器,獲取頁面,這樣就會浪費不少流量,對服務器壓力很大) 可是通常提交咱們用表單 支持跨域
  • ajax 同步體驗很差,能夠無刷新頁面 1.0,2.0 ajax基於表單請求http發過去的,只是發送方式不同 不支持跨域
  • jsop xss攻擊,逐漸接口暴露出去,你們均可以訪問,大多數網站在廢棄中, 逐漸被cors代替
  • cors 跨域資源共享,不須要前臺,直接更改服務端配置
  • nginx 反向代理
  • webpack proxy 反向代理

雙向通訊 鏈接之後,不須要客戶端主動發送請求,服務端能夠主動告訴他,會實時吧最新的信息提交給客戶端,以前咱們的作法是setInterval,可是這就有個問題,假設咱們10分鐘內沒有更新呢,而用websokct當服務端變了以後會主動推送給客戶端,咱們常常應用例如聊天室

  • websocket (基於tcp)

咱們經過node實現服務端,接收前端請求

表單 (會頁面跳轉,若是是get會加個?,若是是post就會跳轉業面,頁面從新渲染,從新請求服務器,獲取頁面,這樣就會浪費不少流量,對服務器壓力很大) 可是通常提交咱們用表單

get post
放到url裏,有限制 不限制大小

get的url形式方便分享 post經過請求體java

<!-- form支持什麼格式提交get post 不識別默認get -->
    <form action="http://localhost:3000/form" method="get">
        用戶名 <input type="text" name="username"><br>
        密碼 <input type="text" name="password"><br>
        <input type="submit">
    </form>
複製代碼

跳轉以後的連接會有http://127.0.0.1:5500/?username=123&password=321form默認支持跨域node

//服務端
let http = require('http');
let url = require('url');
let server = http.createServer(function(req,res){
    let {pathname,query} = url.parse(req.url,true);
    if(pathname === '/form'){
        res.end(JSON.stringify(query))
    }
})
server.listen(3000)
複製代碼

把方法改爲postwebpack

let http = require('http');
let url = require('url');
let querystring = require('querystring');

// let str = "username==123&&password==321";
// // 指定字段之間的分隔符 和 key、value之間的分隔符-》對象
// let obj = querystring.parse(str,'&&','==');
// console.log(obj);

let server = http.createServer(function(req,res){
    let {pathname,query} = url.parse(req.url,true);
    let method = req.method.toLowerCase();//在node中取得的方法名永遠是大寫的
    if(pathname === '/form'){
        if(method === 'get'){
            res.end(JSON.stringify(query))
        }else{
            let buffers = [];
            //接收請求體
            req.on('data',function(data){
                buffers.push(data);
            })
            req.on('end',function(){
                //表單格式接受的都是a=b&c=d 
                //headers[ 'content-type': 'application/x-www-form-urlencoded']
                let str = Buffer.concat(buffers).toString();
                res.end(JSON.stringify(querystring.parse(str)));
            })
        }
    }
})
server.listen(3000)
複製代碼

表單提交的文件比較特殊nginx

<!-- form支持什麼格式提交get post 不識別默認get enctype="multipart/form-data" 多文本,內容類型:多段form表單格式 -->
    <form action="http://localhost:3000/form" method="get">
        用戶名 <input type="text" name="username"><br>
        密碼 <input type="text" name="password"><br>
        <input type="submit">
    </form>
複製代碼

多段form表單格式會用分隔符將內容分離開web

咱們須要將內容解析,或者須要安裝 npm install formidable

let http = require('http');
let url = require('url');
let querystring = require('querystring');
let formidable = require('formidable')
let path = require('path')
// let str = "username==123&&password==321";
// // 指定字段之間的分隔符 和 key、value之間的分隔符-》對象
// let obj = querystring.parse(str,'&&','==');
// console.log(obj);

let server = http.createServer(function(req,res){
    let {pathname,query} = url.parse(req.url,true);
    let method = req.method.toLowerCase();//在node中取得的方法名永遠是大寫的
    if(pathname === '/form'){
        if(method === 'get'){
            res.end(JSON.stringify(query))
        }else{
            var form = new formidable.IncomingForm();
            //fields a=b&c=d文本 files文件
            form.keepExtensions = true;//保留後綴
            form.encoding = 'utf-8';
            form.uploadDir = path.join(__dirname,'./myDir');
            form.parse(req, function(err, fields, files) {
            });
            form.on('end', function() {
                res.end('上傳成功');
            });
        }
    }
})
server.listen(3000)
複製代碼

ajax 同步體驗很差,能夠無刷新頁面 1.0,2.0 ajax基於表單請求http發過去的,只是發送方式不同

<!-- 不支持跨域,協議,主機名,端口號 表單的好處能夠加本身的校驗-->
    <form onsubmit="login(event)" id="form">
        用戶名:
        <input type="text" name="username" required>
        <br> 密碼:
        <input type="text" name="password">
        <br>
        <input type="submit" value="提交">
    </form>
複製代碼
function login(e) {
        let $ = document.querySelector.bind(document);
        function serialized(ele) {
          let arr = [];
          let elements = ele.elements;
          for (let i = 0; i < elements.length; i++) {
            let { type, name, value } = elements[i];
            switch (type) {
              case 'text':
              case 'password':
                arr.push(`${name}=${value}`);
                break
              default:
            }
          }
          return arr.join('&');
        }
        function login(e) {
            //阻止默認行爲
            e.preventDefault();
            //表單序列化 username=123&password=456
            let qs = serialized($('#form'));
            //ajax4步
            let xhr = new XMLHttpRequest();
            xhr.open('GET', `/2.html?${qs}`, true); // true表明是否異步 
            xhr.responseType = 'json';// 服務返回的應該是一個對象
            xhr.timeout = 3000; // 3000過去了尚未數據返回就是超時
            xhr.ontimeout = function () {
                console.log('超時')
            }
            xhr.onerror = function (err) {//斷網
                console.log(err);
            }
            xhr.setRequestHeader('Content-Type', 'application/www-x-form-urlencoded');
            // xhr.setRequestHeader('Content-Type','application/json')
            //readyState 0 表示尚未open 1表明open了 2 表明發送求求 3.接收到了部分請求
            xhr.onreadystatechange = function () {
                console.log(xhr.readyState);
                console.log(xhr.status)
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                        console.log(xhr.response);
                    }
                }
            }
            xhr.send(qs); 
        }
複製代碼

須要啓動服務不然跨域ajax

//服務代碼
let http = require('http');
let url = require('url');
let fs = require('fs');
let path = require('path');
let querystring = require('querystring');
let server = http.createServer(function (req,res) {
    let {pathname,query} = url.parse(req.url,true);
    if(pathname === '/2.html'){
        let method = req.method.toLowerCase();
        if(method === 'get'){ //get方法
            res.end(JSON.stringify(query));
        }else{//post方法
            let buffers = [];
            req.on('data', function (data) {
                buffers.push(data);
            });
            req.on('end', function () {
                let str = Buffer.concat(buffers).toString();
                console.log(str);
                res.end(JSON.stringify(querystring.parse(str)));
            })
        }
        return 
    }
    if(pathname === '/'){
        return fs.createReadStream(path.join(__dirname,'./1.html')).pipe(res);
    }
    let p = path.join(__dirname, pathname);
    fs.stat(p,function (err,stat) {
        if(!err){
        fs.createReadStream(p).pipe(res);
        }else{
        res.statusCode = 404;
        res.end(`NotFound`);
        }
    })
});
server.listen(3000);
複製代碼

post請求和get形似npm

咱們隊上述ajax作個簡單的封裝

function login(e) {
    //阻止默認行爲
    e.preventDefault();
    //表單序列化 username=123&password=456
    let qs = serialized($('#form'));
    //ajax4步
    let xhr = new XMLHttpRequest();
    ajax({
        url: '/2.html',
        method: 'post',
        dataType: 'json',
        contentType:'application/www-x-form-urlencoded',//只有post須要傳
        data: qs
    }).then(data=>{
        console.log(data);
    }).catch(e=>{
        console.log(e);
    });
}
function ajax(options) {
    return new Promise((resolve,reject)=>{
        let {
            url = new Error('url must a string'),
            method = "get",
            dataType = "text",
            data = null,
            success,
            contentType,
            error
        } = options;
        let xhr = new XMLHttpRequest();
        if (method == 'get') {
            xhr.open(method, `${url}?${data}`, true);//若是是get請求,要將數據拼接到url
        } else {
            xhr.open(method, url, true);
            xhr.setRequestHeader('ContentType', contentType);//設置請求頭
        }
        xhr.responseType = dataType;//響應類型
        xhr.onerror = function (err) {
            error && error(err);
            reject(err)
        }
        xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                console.log(xhr.response)
                success && success(xhr.response);
                resolve(xhr.response)
            }
        }
        }
        data = method === 'get' ? null : data;
        xhr.send(data);
    })
}
複製代碼
相關文章
相關標籤/搜索