1. 程式人生 > >Node.js 獲取GET、POST提交的資料

Node.js 獲取GET、POST提交的資料

表單提交過來的資料有兩種方法,一種是GET方式提交,這種提交方法會把表單需要傳輸的資料寫在url上,一起帶過去,另一種是POST方式提交,POST方式提交會把表單資料攜帶在request請求正文中傳遞過去。

針對這兩種不同的提交方法,node裡也有兩種不同的處理方法。先看看如果用GET方式提交,我們該怎麼去處理

獲取GET方式提交的資料

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>
</title> </head> <body> <form action="http://localhost:9998" method="get"> <input type="text" name="user" value="" /> <input type="password" name="passw" value="" /> <input type="submit" value=""/> </form
>
</body> </html>

index.html只是一個簡單的表單網頁,兩個輸入框用作使用者的賬號和密碼輸入,還有一個submit用來提交。

下面是node實現

GETServer.js

var http = require("http");
var url = require("url");

function onRequest(req,resp){
    console.log(url.parse(req.url,true).query);
    //返回響應
    resp.writeHead(200,{"ContentType"
:"text/html;charset=utf-8"}); resp.end(); } //建立server http.createServer(onRequest).listen(9998);

這樣的話就獲取到了表單使用GET方式提交過來的資料
其中req.url 是指req提交過來的url的路由
但是我們會發現一個問題,我們看一下console的列印情況。

{ user: 'asda', passw: 'asddasd' }
{}

我們會發現列印了兩行,第二行被打印出了一個空的JSON物件。這是怎麼回事呢,聽老衲緩緩道來。

在第一次request請求的時候,客戶端會發送一個隱式的請求給伺服器,這個請求就是為了獲取到網頁的圖示(就是每個網頁開啟後Title旁邊的那個小圖示),所以,當我們提交表單資料的時候,實際是觸發了兩次請求,第一次請求favicon.ico ,第二次提交資料,所以我們打印出來的結果就是兩個物件。

so?那麼我們應該怎樣去處理它呢?我們需要在服務端過濾掉請求favicon.ico的請求。
只需加上一段這樣的if就行

if(req.url != "/favicon.ico"){
    console.log(url.parse(req.url,true).query);
}

這樣的話我們再看一下console的列印結果是不是正常了

{ user: 'asda', passw: 'asddasd' }

獲取POST方式提交的資料

開頭我也說過了,用POST方式提交的資料會附帶在請求正文裡面,所以我們需要獲取到附帶在request正文裡的資訊,那具體是怎麼做呢?

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    </head>
    <body>
        <form action="http://localhost:9998" method="post">
            <input type="text" name="user"  value="" />
            <input type="password" name="passw" value="" />
            <input type="submit" value=""/>
        </form>
    </body>
</html>

這裡只做了簡單的修改,把method 從get改為post

POSTServer.js

/**
 * New node file
 */

var http = require("http");
var queryString = require("querystring");

function onRequest(req,resp){
    //過濾掉favicon請求
    if(req.url != "/favicon.ico"){
        //post請求 獲取表單資料
        var obj = null;
        var currentData = "";
        req.on("data",function(data){
            currentData += data;
            obj = queryString.parse(currentData);
        });
        console.log(obj);
        resp.writeHead(200,{"ContentType":"text/html;charset=utf-8"});
        resp.end();
    }
}


//建立server
http.createServer(onRequest).listen(9998);

上面的querystring.parse就能直接把獲取到的資料轉換成JSON物件。
接下來我們來看看控制檯是怎麼列印的

null

what!?
這裡寫圖片描述

為什麼是null!?
這就說明如果要學習Node就得改掉我們寫java ,寫C/C++ 那些非非同步的語言的程式設計習慣,因為這裡的原因之所以是Null是因為Node本身機制的原因

Node的快就在於它處處存在非同步,存在回撥,基於觀察者模式於一身的美男子

這裡我不得不說一下Node的非同步執行機制。
下面我畫一張醜圖僅供大家參考。

這裡寫圖片描述

看不清的朋友右鍵檢視原圖把。
畫的有點醜大家湊合著看,我來簡單的說明一下這幅圖。

整個Node程式在執行的過程中,遇到了sync Event 也就是同步事件,然後直譯器會把它交給一個叫做事件棧(Event Stack)的資料結構,這個棧會不斷的去push同步程式碼,然後執行完畢後pop出來。當程式遇到非同步事件(async Event)的時候,會把它交給別的地方來處理,處理完畢後將結果返回至事件佇列(Event Queue),當Event Stack空閒的時候,就會讓一個Loop來挨個挨個將事件佇列中的事件取出來,放入事件棧裡執行回撥。

這時我們就可以解釋為什麼是null了,因為request 綁定了一個名為data的非同步事件,但是我們console.log(obj);是sync的,所以直譯器會先打印出obj的值,再去事件佇列中取出來放到事件棧中去執行回撥,雖然我們程式碼順序是先賦值,再列印,而結果卻出乎我們意料,是先列印再賦值,對於這種情況的解決辦法,我們初步可以呼叫setTimeout的方法來解決它。setTimeout() 是一個延遲執行的函式,用它可以將我們的console.log(obj);放入佇列尾,這樣的話,我們就能夠實現先賦值再列印了,當然這樣會降低程式的效率。

我們來修改一下程式的程式碼

POSTServer.js

/**
 * New node file
 */

var http = require("http");
var queryString = require("querystring");

function onRequest(req,resp){
    //過濾掉favicon請求
    if(req.url != "/favicon.ico"){
        //post請求 獲取表單資料
        var obj = null;
        var currentData = "";
        req.on("data",function(data){
            currentData += data;
            obj = queryString.parse(currentData);
        });
        setTimeout(function(){
            console.log(obj);
        },1000);
        resp.writeHead(200,{"ContentType":"text/html;charset=utf-8"});
        resp.end();
    }
}


//建立server
http.createServer(onRequest).listen(9998);

這樣的話我們就能看到console打印出來的正常的結果。

{ user: 'asda', passw: 'asddasd' }

完美處理POST、GET請求

接下來我們結合兩種方法來實現不管POST,GET提交的方式我們都能處理。

GETPOSTServer.js

/**
 * New node file
 */

var http = require("http");
var url = require("url");
var queryString = require("querystring");

function onRequest(req,resp){
    //過濾掉favicon請求
    if(req.url != "/favicon.ico"){
        //需要的json物件
        var obj = null;
        //區分get post 請求
        if(req.method == "GET"){
            obj = url.parse(req.url,true).query;
        }
        else{
            //post請求 獲取表單資料
            var currentData = "";
            req.on("data",function(data){
                currentData += data;
                obj = queryString.parse(currentData);
            });
        }
        //新增進事件佇列
        setTimeout(function(){
            console.log(obj);
        },1000);
        write(resp);

    }
}

function write(resp){
    resp.writeHead(200,{"ContentType":"text/html;charset=utf-8"});
    resp.end();
}


//建立server
http.createServer(onRequest).listen(9998);

如果大家發現本篇博文有任何錯誤,都可以在回覆區反饋給我。我會及時改正,共勉!