Node模塊創(chuàng)建及使用,文件操作暗挑,IO交互炸裆,URL解析

目錄

  • 模塊創(chuàng)建以及使用
  • 文件模塊的使用
  • IO鍵盤交互
  • URL解析

一烹看、模塊創(chuàng)建以及使用

  • 什么是模塊
    模塊和文件是一 一對應的墙歪,一個模塊就是一個js文件听系,Node.js提供了exports和require兩個對象,其中exports是模塊公共的接口虹菲,require用于從外部獲取一個模塊的接口,即獲取模塊的exports對象掉瞳。想要在外部用自定義模塊中的方法exports方法暴露出去毕源,通過require引入模塊再調用其方法。
  • 模塊的分類
  • 核心模塊
    如http陕习、fs霎褐、path等该镣,引用《深入淺出Node.js》中的一段話

核心模塊部分在Node源代碼的編譯過程中冻璃,編譯進了二進制執(zhí)行文件。在Node進程啟動時损合,部分核心模塊就被直接加載進內存中省艳,所以這部分核心模塊引入時,文件定位和編譯執(zhí)行這兩個步驟可以省略掉嫁审,并且在路徑分析中優(yōu)先判斷跋炕,所以他的加載速度是最快的。

  • 第三方模塊
    通過NPM安裝的模塊都會放入到node_modules目錄下律适,在引用模塊時和核心模塊類似辐烂,require方法只需寫模塊名一就可以,不需要路徑捂贿。Node在查找這個模塊時會現(xiàn)在本級目錄下查看是否有node_modules目錄纠修,若有看其內是否有相應的模塊,若沒有會去父目錄查找厂僧,以此類推扣草,就像是JavaScript的原型鏈和作用域鏈的查找方式。所以這類模塊的查找會耗時最多,加載最慢德召。

  • 創(chuàng)建模塊
    第一種方式

//mymodule.js
//使用exports向外部暴露方法
var name;
exports.setName=function(isname) {
    name = isname;
}
exports.sayNanme=function (){
    console.log('hello my name is '+name);
}
//getmymodule.js
var myModule =require('./mymodule');
myModule.setName('AngelaMuller');//調用模塊中方法設置屬性
myModule.sayNanme();//調用方法

使用:

muller@ubuntu:~/node$ node getmymodule.js
hello my name is AngelaMuller

第二種方式

//mymodule.js
module.exports =  function (name){
    this.name = name;
    this.sayhello = function(){
        console.log('hello world白魂!'+this.name);
    }
};
//getmymodule.js
var person  = require('./mymodule');
var oneper = new person('AngelaMuller');
oneper.sayhello();

使用:

muller@ubuntu:~/node$ node getmymodule.js
hello world!AngelaMuller
  • 單次加載
    上面的例子有點類似創(chuàng)建一個對象上岗,但實際上和對象又有本質的區(qū)別福荸,因為require不會重復加載模塊,也就是說無論調用多少次require肴掷,獲取的模塊都是同一個
  • 覆蓋exports
    有時我們知識想把一個對象封裝到模塊中敬锐,例如
    定義模塊:singleobejct.js
    引入模塊使用:getSingleObject.js
    繁瑣:exports.hello=hello;
    引入:require("./singleobject").hello;
    簡易:module.exports=hello;
    exports本身僅僅是一個普通的空對象,即{}呆瞻,它是專門用來聲明接口

定義模塊:singleobejct.js

function hello(){
    var name;
    this.setName=function(thyName){
        name=thyName;
    }
    this.sayHello=function(){
        console.log('hello '+name);
    }
}
//exports.hello=hello;
module.exports=hello;    // 定義的方法添加   (簡單的方式)

引入模塊使用:getSingleObject.js

var hello=require('./singleobject');
var he=new hello();
he.setName('marico');  //實例化第一個實例
he.sayHello();
var he2=new hello();  //實例化第二個實例
he2.setName('yfc');
he2.sayHello()

結果輸出:

[root@localhost nodejs]# node getSingleObject.js 
hello marico
hello yfc

繁瑣:exports.hello=hello; //使用這種方式加載在對象中時台夺,在調用使用時比較繁瑣
引入:require("./singleobject").hello;

二、文件操作

node.js模塊是文件操作的封裝痴脾,它提供了文件的讀取颤介,寫入,更名赞赖,刪除滚朵,遍歷目錄,鏈接POSIX文件系統(tǒng)操作前域。與其他模塊不同的是辕近,fs模塊中所有的操作都提供了異步和同步兩個版本,例如匿垄,讀取文件內容函數(shù)異步方法移宅,readFile(),同步方法readFileSync().

  • 同步方式的文件系統(tǒng)調用會導致阻塞,由于Node.js是單線程的椿疗,直到文件調用完成后漏峰,控制權才會被放回主線程,這也就導致了后臺其他線程池中的很多線程不能夠執(zhí)行变丧,從而導致Node.js中一定程度的性能問題芽狗。因此應該盡可能的減少使用同步方式的文件系統(tǒng)的方法調用。
  • 異步調用會被主線程放置在事件隊列中以備隨后運行痒蓬,這使得調用能夠融入Node.js中的事件模型童擎。但在執(zhí)行代碼時,就會變得有點棘手攻晒,因為事件并不能在預期的時候完成顾复,這就需要有一個callback函數(shù)來規(guī)定當調用完成時需要完成的事。(這里可以去深入了解下Node.js的事件隊列)
  • 簡單讀取
    fs.readFile(path,[options],callback);
    fs.readFildSync(path,[options]);

  • 非簡單讀取
    fs.read(fd,buffer,offset,length,position,callback);
    fs.readSync(fd,buffer,offset,length,position);

  • 流式讀取
    fs.createReadStream(path,[options]);

  • fs模塊的其他方法
    驗證文件/目錄路徑的存在性
    fs.exists(path,callback);
    fs.existsSync(path);

注: 同步方法返回true/false鲁捏,異步方法callback僅僅只有一個err對象表示是否刪除成功芯砸。

同步讀取
//引入fs模塊
var fs=require('fs');
fs.readFile('content.txt','UTF-8',function(err,data){
    if(err){
        console.log(err);
    }else{
        console.log(data);
    }
});

//沒有回調函數(shù)
try{
    var data=fs.readFileSync('content.txt','UTF-8');
    console.log(data+"同步式讀取");
}catch(e){
    console.log(e)
}

content.txt 內容

Node.js的文件系統(tǒng)的Api   AngelaMuller

輸出結果:

muller@ubuntu:~/node$ node mymodule.js 
Node.js的文件系統(tǒng)的Api   AngelaMuller同步式讀取
Node.js的文件系統(tǒng)的Api   AngelaMuller

異步讀取文件與readFile相同,而讀取到的文件內容會以函數(shù)返回值的形式返回,如果有錯誤發(fā)生假丧,fs將拋出異常双揪,你需要try和catch捕獲并處理異常。
Node.js from fs.readFileSync() to fs.readFile()
其他方法請查看官方API https://nodejs.org/dist/latest-v4.x/docs/api/fs.html

三包帚、 IO交互

什么是IO交互

簡單點是Node.js的控制臺輸入輸出渔期,I 是input 可讀輸入流 ,O是output 可輸出流渴邦,Node.js也有如同C++和Java的標準輸入輸出進行交互疯趟。

  • 輸入設備
    輸入設備是人向計算機輸入信息的設備,常用的輸入設備有:
    (1)鍵盤---人向計算機輸入信息最基本的設備谋梭;
    (2)鼠標器----一種光標指點設備信峻;
    (3)觸摸屏----一種坐標定位設備,常用于公共查詢系統(tǒng)瓮床。
  • 輸出設備
    輸出設備是直接向人提供計算機運行結果的設備盹舞,常用的輸出設備有:
    (1)顯示器---計算機的主要輸出設備,它與鍵盤一起構成最基本的人機對話環(huán)境;
    (2)打印機---打印機為用戶提供計算機信息的硬拷貝纤垂。常用的打印機有:擊打式矾策、噴墨式和激光打印機。
什么是Readline

Readline是Node.js里實現(xiàn)標準輸入輸出的封裝好的模塊峭沦,通過這個模塊我們可以以逐行的方式讀取數(shù)據(jù)流。
使用require("readline")可以引用模塊逃糟。

如何使用Readline
// 引入readline模塊
const readline = require('readline');

//創(chuàng)建readline接口實例
const rl = readline.createInterface({
    input: process.stdin,  //監(jiān)聽的可讀流 (必填)
    output: process.stdout //逐行讀群鹩恪(Readline)數(shù)據(jù)要寫入的可寫流(可選)
});
rl.setPrompt('What is your name ? > ');//設置提示符
rl.prompt(); //為用戶輸入準備好逐行讀取(Readline),讓用戶有新的地方輸入


rl.on('line', function (str) {
    console.log('my name is : '+str);
});

// close事件監(jiān)聽
rl.on("close", function(){
   // 結束程序
   console.log('Have a great day!');
    process.exit(0);// 結束程序
});

/* v0.10.44 版本似乎有問題 v4.5.0案例
rl.on('line', (line) => {
    var str = line.trim();
    console.log('my name is : '+str);
    
    rl.prompt();
}).on('close', () => {
  console.log('Have a great day!');
  process.exit(0);
});
*/

在close事件的監(jiān)聽里绰咽,我們執(zhí)行了process.exit(0)來使程序退出的操作菇肃,因為readline模塊只要一開始獲取用戶輸入就不會結束,必須使用這種直接的方式來結束程序取募。

輸入與輸出實例
// 引入readline模塊
var readline = require('readline');

var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('line', function(line){
    switch(line.trim()) {
        case 'copy':
            console.log("復制");
            break;
        case 'hello':
            rl.write("Write");
            console.log('world!');
            break;
        case 'close':
            rl.close();
            break;
        default:
            console.log('沒有找到命令琐谤!');
            break;
    }
});
rl.on('close', function() {
    console.log('bye bye');
    process.exit(0);
});

 'line'事件,這個事件就是在用戶輸完一行玩敏,按下回車后就會觸發(fā)的事件斗忌,它會將用戶輸入的數(shù)據(jù)通過回調函數(shù)傳回來,可在此方法里處理用戶輸入的數(shù)據(jù)

命令行輸入與輸出
const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);

rl.setPrompt('OHAI> ');
rl.prompt();

rl.on('line', (line) => {
  switch(line.trim()) {
    case 'hello':
      console.log('world!');
      break;
    default:
      console.log('Say what? I might have heard `' + line.trim() + '`');
      break;
  }
  rl.prompt();
}).on('close', () => {
  console.log('Have a great day!');
  process.exit(0);
});

四旺聚、URL解析

1.URL模塊為URL的解析工具
var url = require('url');
var urlString = 'http://user:pass@best.bluepay.asia:90/p/a/t/h?query=string#hash';
var result = url.parse(urlString);
console.log(result);

//第二個可選參數(shù)設置為true時  query: { query: 'string' },

輸出結果:

muller@ubuntu:~/node$ node url.js
Url {
  protocol: 'http:',
  slashes: true,
  auth: 'user:pass',
  host: 'best.bluepay.asia:90',
  port: '90',
  hostname: 'best.bluepay.asia',
  hash: '#hash',
  search: '?query=string',
  query: 'query=string',
  pathname: '/p/a/t/h',
  path: '/p/a/t/h?query=string',
  href: 'http://user:pass@best.bluepay.asia:90/p/a/t/h?query=string#hash' }

  • href 屬性會被忽略
  • protocol無論是否有末尾的 : (冒號)织阳,會同樣的處理 這些協(xié)議包括 http, https, ftp, gopher, file 后綴是 :// (冒號-斜杠-斜杠). 所有其他的協(xié)議如 mailto, xmpp, aim, sftp, foo, 等 會加上后綴 : (冒號)
  • auth 如果有將會出現(xiàn).
  • hostname 如果 host 屬性沒被定義,則會使用此屬性.
  • port 如果 host 屬性沒被定義砰粹,則會使用此屬性.
  • host 優(yōu)先使用唧躲,將會替代 hostname 和port
  • pathname 將會同樣處理無論結尾是否有/ (斜杠)
  • search 將會替代 query屬性
  • query (object類型; 詳細請看 querystring) 如果沒有 search,將會使用此屬性.
  • search 無論前面是否有 ? (問號),都會同樣的處理
  • hash無論前面是否有# (井號, 錨點),都會同樣處理

2.queryString 模塊

提供了實用程序來處理查詢字符串

  • querystring.stringify(obj, [sep], [eq])

    將JSON對象格式化為查詢字符串格式的字符串弄痹,默認的分隔符為:“&”和“=”饭入,具體可以看一下以下代碼.

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

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

// Suppose gbkEncodeURIComponent function already exists,
// it can encode string with `gbk` encoding
querystring.stringify({ w: '中文', foo: 'bar' }, null, null,
  { encodeURIComponent: gbkEncodeURIComponent })
// returns 'w=%D6%D0%CE%C4&foo=bar'
  • querystring.parse(str, [sep], [eq], [options])

    根據(jù)“&”和“=”將字符串進行分割,反序列化為JSON對象肛真,而options包含的maxKeys默認設置為1000谐丢,如果將其設置為0則表示沒這個限制.

querystring.parse('foo=bar&baz=qux&baz=quux&corge')
// returns { foo: 'bar', baz: ['qux', 'quux'], corge: '' }

// Suppose gbkDecodeURIComponent function already exists,
// it can decode `gbk` encoding string
querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
  { decodeURIComponent: gbkDecodeURIComponent })
// returns { w: '中文', foo: 'bar' }
  • querystring.escape,querystring.unescape

    這兩個內置方法毁欣,分別在上述兩個方法的內置使用庇谆,如果有需要分別格式化和解碼URL字符串。

3. QueryString模塊和Url模塊之間的關系
  url.parse(string).query
                                           |
           url.parse(string).pathname      |
                       |                   |
                       |                   |
                     ------ -------------------
http://localhost:8888/start?foo=bar&hello=world
                                ---       -----
                                 |          |
                                 |          |
              querystring(string)["foo"]    |
                                            |
                         querystring(string)["hello"]

4. 獲取靜態(tài)資源

完整實例(根據(jù)不同的url地址請求不同的文件)

const ip = '192.168.1.223';//主機IP
const port = 3000;//端口號
//引入的組建模塊  http凭疮、url饭耳、fs
const http = require('http');
const urls = require('url');
const fs = require('fs');
//實例化一個服務容器
var server = new http.Server();
//監(jiān)聽一個端口
server.listen(port , ip);
//注冊一個事件處理的on方法
server.on('request' , function(req , res){
    //獲取請求的url地址
    var url = urls.parse(req.url);
    //console.log(url.pathname);
    //根據(jù)path路徑來讀取不同的模板文件
    switch( url.pathname ){
        //顯示首頁
        case '' || '/':
            //讀取文件內容
            fs.readFile('./index.html',function( error, content){
                if(error){
                    //如果有錯誤時,顯示錯誤信息
                    funError();
                }else{
                    //正確時瀏覽器輸出模板文件的內容
                    funAuccess(res,content);
                }
            });
            break;
        //顯示列表頁面
        case '/list':
            fs.readFile('./list.html',function( error, content){
                if(error){
                        funError(res , error);
                }else{
                    funAuccess(res,content);
                }
                });
            break;
        //顯示詳情頁
        case '/show':
            fs.readFile('./show.html',function( error, content){
                if(error){
                    funError(res , error);
                }else{
                    funAuccess(res,content);
                }
            });
            break;
        //獲取靜態(tài)資源的頁面 如:css\js
        default:
            //獲取文件名
            var filename = url.pathname.substring(1);
            //獲取文件名對應的類型值
            var type = getAllType( filename.substring(filename.lastIndexOf('.')+1));
            //測試所用
            //console.log(type);
            //讀取靜態(tài)資源的頁面
            fs.readFile(filename , function( error, content){
                if(error){
                    funError(res , error);
                }else{
                    res.writeHead(200,{'Content-Type' : type});
                    res.write(content);
                    res.end();
                }
            });
            break;
    }

});
//錯誤提示的函數(shù)
function funError(response , error){
    response.writeHead(400,{'Content-Type':'text/plain;charset="utf-8"'});
    response.write(error.message);
    response.end();
}

//正確時輸出文件內容的函數(shù)
function funAuccess(response,cont){
    response.writeHead(200,{'Content-Type':'text/html;charset="utf-8"'});//頭信息
    response.write(cont);//模板文件內容
    response.end();
}


//定義文件類型的函數(shù)
function getAllType(code){
    var type = '';
    switch(code){
          case 'html':
            type = 'text/html;charset=utf-8';
            break;
        case 'js':
            type = 'application/javascript/html;charset=utf-8';
            break;
        case 'css':
            type = 'text/css;charset=utf-8';
            break;
            case 'text':
            type = 'text/plain;charset=utf-8';
            break;
        case 'manifest':
            type = 'text/cache-manifest;charset=utf-8';
            break;
        default:
            type = 'application/octet-stream';
            break;
    }
    return type;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末执解,一起剝皮案震驚了整個濱河市寞肖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衰腌,老刑警劉巖新蟆,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異右蕊,居然都是意外死亡琼稻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門饶囚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帕翻,“玉大人,你說我怎么就攤上這事萝风∴值В” “怎么了?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵规惰,是天一觀的道長睬塌。 經(jīng)常有香客問我,道長歇万,這世上最難降的妖魔是什么揩晴? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮堕花,結果婚禮上文狱,老公的妹妹穿的比我還像新娘。我一直安慰自己缘挽,他們只是感情好瞄崇,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布呻粹。 她就那樣靜靜地躺著,像睡著了一般苏研。 火紅的嫁衣襯著肌膚如雪等浊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天摹蘑,我揣著相機與錄音筹燕,去河邊找鬼。 笑死衅鹿,一個胖子當著我的面吹牛撒踪,可吹牛的內容都是我干的。 我是一名探鬼主播大渤,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼制妄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泵三?” 一聲冷哼從身側響起耕捞,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎烫幕,沒想到半個月后俺抽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡较曼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年磷斧,在試婚紗的時候發(fā)現(xiàn)自己被綠了街立。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痕届。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖留特,靈堂內的尸體忽然破棺而出伏恐,到底是詐尸還是另有隱情,我是刑警寧澤栓霜,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布翠桦,位于F島的核電站,受9級特大地震影響胳蛮,放射性物質發(fā)生泄漏销凑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一仅炊、第九天 我趴在偏房一處隱蔽的房頂上張望斗幼。 院中可真熱鬧,春花似錦抚垄、人聲如沸蜕窿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桐经。三九已至毁兆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阴挣,已是汗流浹背气堕。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留畔咧,地道東北人茎芭。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像誓沸,于是被迫代替她去往敵國和親梅桩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內容

  • Node.js是目前非潮谓椋火熱的技術摘投,但是它的誕生經(jīng)歷卻很奇特。 眾所周知虹蓄,在Netscape設計出JavaScri...
    w_zhuan閱讀 3,615評論 2 41
  • 個人入門學習用筆記犀呼、不過多作為參考依據(jù)。如有錯誤歡迎斧正 目錄 簡書好像不支持錨點薇组、復制搜索(反正也是寫給我自己看...
    kirito_song閱讀 2,472評論 1 37
  • Node.js是目前非惩獗郏火熱的技術,但是它的誕生經(jīng)歷卻很奇特律胀。 眾所周知宋光,在Netscape設計出JavaScri...
    Myselfyan閱讀 4,072評論 2 58
  • topics: 1.The Node.js philosophy 2.The reactor pattern 3....
    宮若石閱讀 1,080評論 0 1
  • 卷首 1. 愛情,如果要遠離 別猶豫炭菌,快些離去吧 別讓我等待中疲憊 2. 在手機的震動叮咚中 我原以為 每次都是你...
    可回閱讀 224評論 2 2