Node API介紹與簡單使用

Node教程

什麼是NodeJS

JS是腳本語言,腳本語言都須要一個解析器才能運行。對於寫在HTML頁面裏的JS,瀏覽器充當瞭解析器的角色。而對於須要獨立運行的JS,NodeJS就是一個解析器。php

每一種解析器都是一個運行環境,不但容許JS定義各類數據結構,進行各類計算,還容許JS使用運行環境提供的內置對象和方法作一些事情。例如運行在瀏覽器中的JS的用途是操做DOM,瀏覽器就提供了document之類的內置對象。而運行在NodeJS中的JS的用途是操做磁盤文件或搭建HTTP服務器,NodeJS就相應提供了fshttp等內置對象。css

Node官網

官網APIhtml

中文翻譯java

Buffer

在引入 TypedArray 以前,JavaScript 語言沒有用於讀取或操做二進制數據流的機制。 Buffer 類是做爲 Node.js API 的一部分引入的,用於在 TCP 流、文件系統操做、以及其餘上下文中與八位字節流進行交互。node

Buffer對象是Node處理二進制數據的一個接口。它是Node原生提供的全局對象,能夠直接使用,不須要require(‘buffer’),個人理解其實buffer就是個字節數組。linux

  • 實例化
    • Buffer.from(array)
    • Buffer.from(string)
    • Buffer.alloc(size)
  • 功能方法
    • Buffer.isEncoding() 判斷是否支持該編碼
    • Buffer.isBuffer() 判斷是否爲Buffer
    • Buffer.byteLength() 返回指定編碼的字節長度,默認utf8
    • Buffer.concat() 將一組Buffer對象合併爲一個Buffer對象
  • 實例方法
    • write() 向buffer對象中寫入內容web

    • slice() 截取新的buffer對象express

    • toString() 把buf對象轉成字符串json

    • toJson() 把buf對象轉成json形式的字符串windows

      toJSON方法不須要顯式調用,當JSON.stringify方法調用的時候會自動調用toJSON方法

核心模塊API

路徑操做Path

path 模塊提供用於處理文件路徑和目錄路徑的實用工具。 它可使用如下方式訪問:

const path = require('path');
Path對象
const path = require('path');
console.log(path)
// 結果:
// { resolve: [Function: resolve],
// normalize: [Function: normalize],
// isAbsolute: [Function: isAbsolute],
// join: [Function: join],
// relative: [Function: relative],
// toNamespacedPath: [Function: toNamespacedPath],
// dirname: [Function: dirname],
// basename: [Function: basename],
// extname: [Function: extname],
// format: [Function: format],
// parse: [Function: parse],
// sep: '\\',
// delimiter: ';',
// win32: [Circular],
// posix:
// { resolve: [Function: resolve],
// normalize: [Function: normalize],
// isAbsolute: [Function: isAbsolute],
// join: [Function: join],
// relative: [Function: relative],
// toNamespacedPath: [Function: toNamespacedPath],
// dirname: [Function: dirname],
// basename: [Function: basename],
// extname: [Function: extname],
// format: [Function: format],
// parse: [Function: parse],
// sep: '/',
// delimiter: ':',
// win32: [Circular],
// posix: [Circular],
// _makeLong: [Function: toNamespacedPath] },
// _makeLong: [Function: toNamespacedPath] }
獲取路徑的最後一部分path.basename
console.log(path.basename('/foo/bar/baz/asdf/quux.html'));
// 返回: 'quux.html'
console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html'));
// 返回: 'quux'
獲取路徑path.dirname
console.log(__dirname);
// 返回 此文件目錄的絕對路徑C:\Users\xiaox\Desktop\code
console.log(__filename)
// 返回 此文件的絕對路徑C:\Users\xiaox\Desktop\code\1.js
console.log(path.dirname('/abc/qqq/www/abc'));
// 返回 /abc/qqq/www
console.log(path.dirname('/abc/qqq/www/abc.txt'));
// 返回 /abc/qqq/www
獲取擴展名path.extname(path)
console.log(path.extname('index.html'));
// 返回 .html
路徑的格式化處理path.format(pathObject)與path.parse(path)

path.format(pathObject) obj->string

let objpath = { 
  root: 'C:\\',
  dir:
   'C:\\Users\\xiaox\\Desktop\\code',
  base: '1.js',
  ext: '.js',
  name: '1' 
};
console.log(path.format(objpath));
// 返回C:\Users\xiaox\Desktop\code\1.js

當爲 pathObject 提供屬性時,注意如下組合,其中一些屬性優先於另外一些屬性:

  • 若是提供了 pathObject.dir,則忽略 pathObject.root
  • 若是 pathObject.base 存在,則忽略 pathObject.extpathObject.name

path.parse(path) string->obj

console.log(path.parse(__filename));
/* { root: 'C:\\', dir: 'C:\\Users\\xiaox\\Desktop\\code', base: '1.js', ext: '.js', name: '1' } */
判斷是否爲絕對路徑path.isAbsolute(path)
console.log(path.isAbsolute('/foo/bar'));
// 返回true
console.log(path.isAbsolute('C:/foo/..'));
// 返回true
拼接路徑path.join([…paths])

(…表示上層路徑;.表示當前路徑),在鏈接路徑的時候會格式化路徑

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'

path.join('foo', {}, 'bar');
// 拋出 'TypeError: Path must be a string. Received {}'
規範化路徑path.normalize(path)
console.log(path.normalize('/foo/bar//baz/asdf/quux/..'));
// 返回: '/foo/bar/baz/asdf'
console.log(path.normalize('C:\\temp\\\\foo\\bar\\..\\'));
// 返回: 'C:\\temp\\foo\\'
計算相對路徑path.relative(from, to)
console.log(path.relative('/data/orandea/test/aaa','/data/orandea/impl/bbb'));
// 返回: '../../impl/bbb'
console.log(path.relative('C:\\orandea\\test\\aaa','C:\\orandea\\impl\\bbb'));
// 返回: '..\\..\\impl\\bbb'
解析路徑path.resolve([…paths])

給定的路徑序列從右到左進行處理,每一個後續的 path 前置,直到構造出一個絕對路徑

path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// 若是當前工做目錄是 /home/myself/node,
// 則返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'
兩個特殊屬性path.seppath.delimiter
console.log(path.delimiter);//表示路徑分隔符(windows是\ Linux是/)POSIX 上:

console.log(process.env.PATH);
// 打印: '/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin'

process.env.PATH.split(path.delimiter);
// 返回: ['/usr/bin', '/bin', '/usr/sbin', '/sbin', '/usr/local/bin']
在 Windows 上:

console.log(process.env.PATH);
// 打印: 'C:\Windows\system32;C:\Windows;C:\Program Files\node\'

process.env.PATH.split(path.delimiter);
// 返回: ['C:\\Windows\\system32', 'C:\\Windows', 'C:\\Program Files\\node\\']
------------------------------------------------------------------------------
console.log(path.sep);//環境變量分隔符(windows中使用; linux中使用:)POSIX 上:

'foo/bar/baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']
在 Windows 上:

'foo\\bar\\baz'.split(path.sep);
// 返回: ['foo', 'bar', 'baz']

在 Windows 上,正斜槓(/)和反斜槓(\)都被接受爲路徑片斷分隔符。 可是, path 方法只添加反斜槓(\)。

文件操做Fs

/*
    異步I/O input/output
    一、文件操做
    二、網絡操做

    在瀏覽器中也存在異步操做:
    一、定時任務
    二、事件處理
    三、Ajax回調處理

    js的運行時單線程的
    引入事件隊列機制

    Node.js中的事件模型與瀏覽器中的事件模型相似
    單線程+事件隊列

    Node.js中異步執行的任務:
    一、文件I/O
    二、網絡I/O

    基於回調函數的編碼風格
*/
查看文件狀態及信息獲取fs.Stats 類fs.stat/fs.statSync
Stats {
  dev: 2114,//該文件的設備的數字標識符
  ino: 48064969,//文件系統特定的文件索引節點編號
  mode: 33188,//描述文件類型和模式的位字段
  nlink: 1,//文件存在的硬連接數
  uid: 85,//擁有該文件(POSIX)的用戶的數字型用戶標識符
  gid: 100,//擁有該文件(POSIX)的羣組的數字型羣組標識符
  rdev: 0,//若是文件被視爲特殊文件,則此值爲數字型設備標識符
  size: 527,//文件的大小(以字節爲單位)
  blksize: 4096,//用於 I/O 操做的文件系統塊的大小
  blocks: 8,//爲此文件分配的塊數
  atimeMs: 1318289051000.1,//代表上次訪問此文件的時間戳,以 POSIX 紀元以來的毫秒數表示
  mtimeMs: 1318289051000.1,//代表上次修改此文件的時間戳,以 POSIX 紀元以來的毫秒數表示
  ctimeMs: 1318289051000.1,//代表上次更改文件狀態的時間戳,以 POSIX 紀元以來的毫秒數表示
  birthtimeMs: 1318289051000.1,//代表此文件的建立時間的時間戳,以 POSIX 紀元以來的毫秒數表示
  atime: Mon, 10 Oct 2011 23:24:11 GMT,//代表上次訪問此文件的時間戳 文件訪問時間
  mtime: Mon, 10 Oct 2011 23:24:11 GMT,//代表上次修改此文件的時間戳 文件數據發生變化的時間
  ctime: Mon, 10 Oct 2011 23:24:11 GMT,//代表上次更改文件狀態的時間戳 文件的狀態信息發生變化的時間(好比文件的權限)
  birthtime: Mon, 10 Oct 2011 23:24:11 GMT //表示此文件的建立時間的時間戳 文件建立的時間
}

經常使用判斷是否爲常規文件stats.isFile()和文件目錄stats.isDirectory()返回布爾值

fs.stat(path[, options], callback)

// const fs = require('fs');

// const pathsToCheck = ['./txtDir', './txtDir/file.txt'];

//異步操做
// for (let i = 0; i < pathsToCheck.length; i++) {
// fs.stat(pathsToCheck[i], function(err, stats) {
// if(stats.isFile()){
// console.log(pathsToCheck[i]+'---文件');
// console.log(stats)
// }else if(stats.isDirectory()){
// console.log(pathsToCheck[i]+'---目錄');
// console.log(stats)
// }else{
// console.log(err)
// }
// });
// }

// 同步操做Sync
// console.log(1);
// let ret = fs.statSync('./data.txt');
// console.log(ret);
// console.log(2);
讀文件操做fs.readFile/fs.readFileSync
/*
    讀文件操做
*/
const fs = require('fs');
const path = require('path');

let strpath = path.join(__dirname,'data.txt');
fs.readFile(strpath,(err,data)=>{
    if(err) return;
    console.log(data.toString());
});

若是有第二個參數而且是編碼,那麼回調函數獲取到的數據就是字符串
若是沒有第二個參數,那麼獲得的就是Buffer實例對象
fs.readFile(strpath,'utf8',(err,data)=>{
    if(err) return;
    // console.log(data.toString());
    console.log(data);
});

同步操做
let ret = fs.readFileSync(strpath,'utf8');
console.log(ret);
寫文件操做fs.writeFile/fs.writeFileSync
/* 寫文件操做 */
const fs = require('fs');
const path = require('path');

// 異步操做
let strpath = path.join(__dirname,'data.txt');
fs.writeFile(strpath,'hello nihao','utf8',(err)=>{
    if(!err){
        console.log('文件寫入成功');
    }
});

let buf = Buffer.from('hi');
fs.writeFile(strpath,buf,'utf8',(err)=>{
    if(!err){
        console.log('文件寫入成功');
    }
});

// 同步操做
fs.writeFileSync(strpath,'tom and jerry');
大文件操做(流式操做)fs.createReadStream/fs.createWriteStream
將文件從一個地方寫入另外一個地方
const path = require('path');
const fs = require('fs');

let spath = path.join(__dirname,'../03-source','file.zip');
let dpath = path.join('C:\\Users\\www\\Desktop','file.zip');

let readStream = fs.createReadStream(spath);
let writeStream = fs.createWriteStream(dpath);

// 基於事件的處理方式
// $('input[type=button]').on('click',function(){
// console.log('hello');
// });

方法一
// -----------------------------------
let num = 1;
readStream.on('data',(chunk)=>{
    num++;
    writeStream.write(chunk);
});

readStream.on('end',()=>{
    console.log('文件處理完成'+num);
});

方法二
// -----------------------------------

// pipe的做用直接把輸入流和輸出流
readStream.pipe(writeStream);

方法三
// ----------------------------------
fs.createReadStream(spath).pipe(fs.createWriteStream(dpath));
目錄操做
  • 建立目錄fs.mkdir(path[, mode], callback)/fs.mkdirSync(path[, mode])

    const path = require('path');
    const fs = require('fs');
    // 建立目錄
    fs.mkdir(path.join(__dirname,'abc'),(err)=>{
        console.log(err);
    });
    fs.mkdirSync(path.join(__dirname,'hello'));
    
    
    // 建立 /tmp/a/apple 目錄,不管是否存在 /tmp 和 /tmp/a 目錄。
    // recursive 屬性(指示是否應建立父文件夾)的對象
    fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
      if (err) throw err;
    });
  • 讀取目錄fs.readdir(path[, options], callback)/fs.readdirSync(path[, options])

    const path = require('path');
    const fs = require('fs');
    // 讀取目錄
    fs.readdir(__dirname,(err,files)=>{
        files.forEach((item,index)=>{
            fs.stat(path.join(__dirname,item),(err,stat)=>{
                if(stat.isFile()){
                    console.log(item,'文件');
                }else if(stat.isDirectory()){
                    console.log(item,'目錄');
                }
            });
        });
    });
    
    let files = fs.readdirSync(__dirname);
    files.forEach((item,index)=>{
        fs.stat(path.join(__dirname,item),(err,stat)=>{
            if(stat.isFile()){
                console.log(item,'文件');
            }else if(stat.isDirectory()){
                console.log(item,'目錄');
            }
        });
    });
  • 刪除目錄fs.rmdir(path, callback)/fs.rmdirSync(path)

    // 刪除目錄
    fs.rmdir(path.join(__dirname,'abc'),(err)=>{
        console.log(err);
    });
    
    fs.rmdirSync(path.join(__dirname,'qqq'));

文件操做案例

/* 文件操做案例(初始化目錄結構) */
const path = require('path');
const fs = require('fs');

let root = 'C:\\Users\\www\\Desktop';
let fileContent = ` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div>welcome to this</div> </body> </html> `;

// 初始化數據
let initData = {
    projectName : 'mydemo',
    data : [{
        name : 'img',
        type : 'dir'
    },{
        name : 'css',
        type : 'dir'
    },{
        name : 'js',
        type : 'dir'
    },{
        name : 'index.html',
        type : 'file'
    }]
}

// 建立項目跟路徑
fs.mkdir(path.join(root,initData.projectName),(err)=>{
    if(err) return;
    // 建立子目錄和文件
    initData.data.forEach((item)=>{
        if(item.type == 'dir'){
            // 建立子目錄
            fs.mkdirSync(path.join(root,initData.projectName,item.name));
        }else if(item.type == 'file'){
            // 建立文件並寫入內容
            fs.writeFileSync(path.join(root,initData.projectName,item.name),fileContent);
        }
    });
});

服務器操做Http

傳統的動態網站開發須要應用軟件
PHP : Apache + php模塊
java :Tomcat 、Weblogic
Node.js  : 不須要應用軟件(能夠本身實現)

/*
    Node.js的Web開發相關的內容:
    一、Node.js不須要依賴第三方應用軟件(Apache),能夠基於api本身實現
    二、實現靜態資源服務器
    三、路由處理
    四、動態網站
    五、模板引擎
    六、get和post參數傳遞和處理

    Web開發框架:express
*/
建立服務器[http.createServer(options][, requestListener])
const http = require('http');
// // 建立服務器實例對象
let server = http.createServer();
console.log(server)

Server {
  _events:
   [Object: null prototype] { connection: [Function: connectionListener] },
  _eventsCount: 1,
  _maxListeners: undefined,
  _connections: 0,
  _handle: null,
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,//超時時間(以毫秒爲單位)。默認值: 120000(2 分鐘)
  keepAliveTimeout: 5000,//超時時間(以毫秒爲單位)。默認值: 5000(5 秒)更改此值僅影響到服務器的新鏈接,而不影響任何現有鏈接
  maxHeadersCount: null,//限制最大傳入請求頭數。 若是設置爲 0,則不會應用任何限制 默認值: 2000
  headersTimeout: 40000,//限制解析器等待接收完整 HTTP 請求頭的時間 默認值: 40000
  [Symbol(IncomingMessage)]:
   { [Function: IncomingMessage]
     super_:
      { [Function: Readable]
        ReadableState: [Function: ReadableState],
        super_: [Function],
        _fromList: [Function: fromList] } },
  [Symbol(ServerResponse)]:
   { [Function: ServerResponse] super_: { [Function: OutgoingMessage] super_: [Function] } },
  [Symbol(asyncId)]: -1 }

http.createServer方法會返回一個http.Server對象實例,requestListener可選參數傳入時,將作爲http.Server對象'request'事件的監聽器。

發送請求http.server類下的request事件

每次有請求時都會觸發。 每一個鏈接可能有多個請求(在 HTTP Keep-Alive 鏈接的狀況下)。

/* 初步實現服務器功能 */
const http = require('http');
// -----------------------------
方法一:
// 建立服務器實例對象
let server = http.createServer();
console.log(server)
// 綁定請求事件
server.on('request',(req,res)=>{
    res.end('hello');
});
// 監聽端口
server.listen(3000);
// -----------------------------
方法二:
http.createServer((req,res)=>{
    res.end('ok');//response.end([data[, encoding]][, callback])
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});

res.end()就是上述response類的方法;[response.end(data[, encoding]][, callback])

res.end('ok','utf-8',()=>{
	console.log('一切正常')
});
啓動 HTTP 服務器監聽鏈接server.listen()

此方法與 net.Server 中的 server.listen() 相同。

上一例子也可,詳細可見官方api
server.listen({
  host: 'localhost',
  port: 80,
  exclusive: true
});
請求路徑分發http.ServerResponse 類

一、req對象是Class: http.IncomingMessage的實例對象
二、res對象是Class: http.ServerResponse的實例對象

const http = require('http');
http.createServer((req,res)=>{
    // req.url能夠獲取URL中的路徑(端口以後部分)
    // res.end(req.url);
    if(req.url.startsWith('/index')){
        // write向客戶端響應內容,能夠寫屢次
        res.write('hello');
        res.write('hi');
        res.write('nihao');
        // end方法用來完成響應,只能執行一次
        res.end();
    }else if(req.url.startsWith('/about')){
        res.end('about');
    }else{
        res.end('no content');
    }
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});

res.write()就是上述response類的方法;[response.write(chunk, encoding][, callback])

/* 響應完整的頁面信息 */
const http = require('http');
const path = require('path');
const fs = require('fs');

// 根據路徑讀取文件的內容,而且響應到瀏覽器端
let readFile = (url,res) => {
    fs.readFile(path.join(__dirname,'www',url),'utf8',(err,fileContent)=>{
        if(err){
            res.end('server error');
        }else{
            res.end(fileContent);
        }
    });
}

http.createServer((req,res)=>{
    // 處理路徑的分發
    if(req.url.startsWith('/index')){
        readFile('index.html',res);
    }else if(req.url.startsWith('/about')){
        readFile('about.html',res);
    }else if(req.url.startsWith('/list')){
        readFile('list.html',res);
    }else{
        // 設置相應類型和編碼
        res.writeHead(200,{
            'Content-Type':'text/plain; charset=utf8'
        });
        res.end('頁面被狗狗叼走了');
    }
}).listen(3000,'192.168.0.106',()=>{
    console.log('running...');
});

設置響應頭[response.writeHead(statusCode, statusMessage][, headers])response.setHeader(name, value)

當使用 response.setHeader() 設置響應頭時,它們將與傳給 response.writeHead() 的任何響應頭合併,其中 response.writeHead() 的響應頭優先。

// 返回 content-type = text/plain
const server = http.createServer((req, res) => {
  res.setHeader('Content-Type', 'text/html');
  res.setHeader('X-Foo', 'bar');
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('ok');
});

解析接口操做URL

URL對象
const url = require('url');
console.log(url)

{ Url: [Function: Url],
  parse: [Function: urlParse],
  resolve: [Function: urlResolve],
  resolveObject: [Function: urlResolveObject],
  format: [Function: urlFormat],
  URL: [Function: URL],
  URLSearchParams: [Function: URLSearchParams],
  domainToASCII: [Function: domainToASCII],
  domainToUnicode: [Function: domainToUnicode],
  pathToFileURL: [Function: pathToFileURL],
  fileURLToPath: [Function: fileURLToPath] 
}
GET參數處理[url.parse(urlString, parseQueryString[, slashesDenoteHost]])

parse方法的做用就是把URL字符串轉化爲對象

const url = require('url');
let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java';
let ret = url.parse(str)
console.log(ret)
//如下能夠參展urlObject
Url {
  protocol: 'http:',//協議
  slashes: true,// url裏characters (/)的是true,不然false
  auth: null,//用戶名和密碼
  host: 'www.baidu.com',//主機地址 主機名+端口
  port: null,//端口
  hostname: 'www.baidu.com',//主機名
  hash: null,//characters (#)
  search: '?flag=123&keyword=java',//查詢參數
  query: 'flag=123&keyword=java',//去掉?的查詢參數
  pathname: '/abc/qqq',//路徑名
  path: '/abc/qqq?flag=123&keyword=java',//路徑
  href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' //完整url
}

第二個參數parseQueryString其實將query.parse了

const url = require('url');
let str = 'http://www.baidu.com/abc/qqq?flag=123&keyword=java';
let ret = url.parse(str,true)
console.log(ret)
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.baidu.com',
  port: null,
  hostname: 'www.baidu.com',
  hash: null,
  search: '?flag=123&keyword=java',
  query: [Object: null prototype] { flag: '123', keyword: 'java' },
  pathname: '/abc/qqq',
  path: '/abc/qqq?flag=123&keyword=java',
  href: 'http://www.baidu.com/abc/qqq?flag=123&keyword=java' }
GET參數處理url.format(URL[, options])

format的做用就是把對象轉化爲標準的URL字符串

url.format({
  protocol: 'https',
  hostname: 'example.com',
  pathname: '/some/path',
  query: {
    page: 1,
    format: 'json'
  }
});

// => 'https://example.com/some/path?page=1&format=json'

查詢字符串Querystring

querystring 模塊提供用於解析和格式化 URL 查詢字符串的實用工具。 它可使用如下方式訪問:

const querystring = require('querystring');
POST參數處理 querystring.parse(str[, sep[, eq[, options]]])

parse方法的做用就是把字符串轉成對象

  • str string 要解析的 URL 查詢字符串。
  • sep string 用於在查詢字符串中分隔鍵值對的子字符串。默認值: '&'
  • eq string 用於在查詢字符串中分隔鍵和值的子字符串。默認值: '='
  • options object
    • decodeURIComponent funciton 解碼查詢字符串中的百分比編碼字符時使用的函數。默認值: querystring.unescape()
    • maxKeys number 指定要解析的鍵的最大數量。指定 0 可移除鍵的計數限制。默認值: 1000

querystring.parse() 方法將 URL 查詢字符串 str 解析爲鍵值對的集合。

例如,查詢字符串 'foo=bar&abc=xyz&abc=123' 被解析爲:

const querystring = require('querystring');
let param = 'foo=bar&abc=xyz&abc=123';
let obj = querystring.parse(param);
console.log(obj);
{
  foo: 'bar',
  abc: ['xyz', '123']
}

querystring.parse() 方法返回的對象不是原型繼承自 JavaScript Object。 這意味着典型的 Object 方法如 obj.toString()obj.hasOwnProperty() 等都沒有定義而且不起做用。

POST參數處理 querystring.stringify(str[, sep[, eq[, options]]])

stringify的做用就是把對象轉成字符串

  • obj object 要序列化爲 URL 查詢字符串的對象。
  • sep string 用於在查詢字符串中分隔鍵值對的子字符串。默認值: '&'
  • eq string 用於在查詢字符串中分隔鍵和值的子字符串。默認值: '='
  • options
    • encodeURIComponent function 在查詢字符串中將 URL 不安全字符轉換爲百分比編碼時使用的函數。默認值: querystring.escape()

querystring.stringify() 方法經過迭代對象的自身屬性從給定的 obj 生成 URL 查詢字符串。

它序列化了傳入 obj 中的如下類型的值: | | | <string[]> | <number[]> | <boolean[]>。 任何其餘輸入值都將被強制轉換爲空字符串。

querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='

querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'

let obj1 = {
    flag : '123',
    abc : ['hello','hi']
}
let str1 = querystring.stringify(obj1);
console.log(str1);
簡單POST請求案例
const querystring = require('querystring');
const http = require('http');

http.createServer((req,res)=>{
    if(req.url.startsWith('/login')){
        let pdata = '';
        req.on('data',(chunk)=>{
            // 每次獲取一部分數據
            pdata += chunk;
        });

        req.on('end',()=>{
            // 這裏才能獲得完整的數據
            console.log(pdata);
            let obj = querystring.parse(pdata);
            res.end(obj.username+'-----'+obj.password);
        });
    }
}).listen(3000,()=>{
    console.log('running...');
})
//這裏能夠本身用postman調試