Node初學(xué)者入門汽馋,一本全面的NodeJS教程

JavaScript與Node.js

JavaScript與你

拋開技術(shù)偷遗,我們先來聊聊你以及你和JavaScript的關(guān)系醉拓。本章的主要目的是想讓你看看伟姐,對你而言是否有必要繼續(xù)閱讀后續(xù)章節(jié)的內(nèi)容收苏。

如果你和我一樣,那么你很早就開始利用HTML進(jìn)行“開發(fā)”愤兵,正因如此鹿霸,你接觸到了這個叫JavaScript有趣的東西,而對于JavaScript秆乳,你只會基本的操作——為web頁面添加交互懦鼠。

而你真正想要的是“干貨”,你想要知道如何構(gòu)建復(fù)雜的web站點(diǎn) —— 于是屹堰,你學(xué)習(xí)了一種諸如PHP肛冶、Ruby、Java這樣的編程語言扯键,并開始書寫“后端”代碼睦袖。

與此同時,你還始終關(guān)注著JavaScript忧陪,隨著通過一些對jQuery扣泊,Prototype之類技術(shù)的介紹,你慢慢了解到了很多JavaScript中的進(jìn)階技能嘶摊,同時也感受到了JavaScript絕非僅僅是window.open()那么簡單延蟹。 .

不過,這些畢竟都是前端技術(shù)叶堆,盡管當(dāng)想要增強(qiáng)頁面的時候阱飘,使用jQuery總讓你覺得很爽,但到最后虱颗,你頂多是個JavaScript用戶沥匈,而非JavaScript開發(fā)者

然后忘渔,出現(xiàn)了Node.js高帖,服務(wù)端的JavaScript,這有多酷捌枇浮散址?

于是,你覺得是時候該重新拾起既熟悉又陌生的JavaScript了宣赔。但是別急预麸,寫Node.js應(yīng)用是一件事情;理解為什么它們要以它們書寫的這種方式來書寫則意味著——你要懂JavaScript儒将。這次是玩真的了吏祸。

問題來了: 由于JavaScript真正意義上以兩種,甚至可以說是三種形態(tài)存在(從中世紀(jì)90年代的作為對DHTML進(jìn)行增強(qiáng)的小玩具钩蚊,到像jQuery那樣嚴(yán)格 意義上的前端技術(shù)贡翘,一直到現(xiàn)在的服務(wù)端技術(shù))蹈矮,因此,很難找到一個“正確”的方式來學(xué)習(xí)JavaScript床估,使得讓你書寫Node.js應(yīng)用的時候感覺 自己是在真正開發(fā)它而不僅僅是使用它含滴。

因為這就是關(guān)鍵: 你本身已經(jīng)是個有經(jīng)驗的開發(fā)者诱渤,你不想通過到處尋找各種解決方案(其中可能還有不正確的)來學(xué)習(xí)新的技術(shù)丐巫,你要確保自己是通過正確的方式來學(xué)習(xí)這項技術(shù)。

當(dāng)然了勺美,外面不乏很優(yōu)秀的學(xué)習(xí)JavaScript的文章递胧。但是,有的時候光靠那些文章是遠(yuǎn)遠(yuǎn)不夠的赡茸。你需要的是指導(dǎo)缎脾。

本書的目標(biāo)就是給你提供指導(dǎo)。更多學(xué)習(xí)資料請點(diǎn)擊此處

簡短申明

業(yè)界有非常優(yōu)秀的JavaScript程序員占卧。而我并非其中一員遗菠。

我就是上一節(jié)中描述的那個我。我熟悉如何開發(fā)后端web應(yīng)用华蜒,但是對“真正”的JavaScript以及Node.js辙纬,我都只是新手。我也只是最近學(xué)習(xí)了一些JavaScript的高級概念叭喜,并沒有實(shí)踐經(jīng)驗贺拣。

因此,本書并不是一本“從入門到精通”的書捂蕴,更像是一本“從初級入門到高級入門”的書譬涡。

如果成功的話,那么本書就是我當(dāng)初開始學(xué)習(xí)Node.js最希望擁有的教程啥辨。

服務(wù)端JavaScript

JavaScript最早是運(yùn)行在瀏覽器中涡匀,然而瀏覽器只是提供了一個上下文,它定義了使用JavaScript可以做什么溉知,但并沒有“說”太多關(guān)于 JavaScript語言本身可以做什么陨瘩。事實(shí)上,JavaScript是一門“完整”的語言: 它可以使用在不同的上下文中着倾,其能力與其他同類語言相比有過之而無不及拾酝。

Node.js事實(shí)上就是另外一種上下文,它允許在后端(脫離瀏覽器環(huán)境)運(yùn)行JavaScript代碼卡者。

要實(shí)現(xiàn)在后臺運(yùn)行JavaScript代碼蒿囤,代碼需要先被解釋然后正確的執(zhí)行。Node.js的原理正是如此崇决,它使用了Google的V8虛擬機(jī) (Google的Chrome瀏覽器使用的JavaScript執(zhí)行環(huán)境)材诽,來解釋和執(zhí)行JavaScript代碼底挫。

除此之外,伴隨著Node.js的還有許多有用的模塊脸侥,它們可以簡化很多重復(fù)的勞作建邓,比如向終端輸出字符串。

因此睁枕,Node.js事實(shí)上既是一個運(yùn)行時環(huán)境官边,同時又是一個庫。

要使用Node.js,首先需要進(jìn)行安裝外遇。關(guān)于如何安裝Node.js注簿,這里就不贅述了,可以直接參考官方的安裝指南跳仿。安裝完成后诡渴,繼續(xù)回來閱讀本書下面的內(nèi)容。

“Hello World”

好了菲语,“廢話”不多說了妄辩,馬上開始我們第一個Node.js應(yīng)用:“Hello World”。

打開你最喜歡的編輯器山上,創(chuàng)建一個helloworld.js文件眼耀。我們要做就是向STDOUT輸出“Hello World”,如下是實(shí)現(xiàn)該功能的代碼:

console.log("Hello World");

保存該文件胶哲,并通過Node.js來執(zhí)行:

node helloworld.js

正常的話畔塔,就會在終端輸出Hello World

好吧鸯屿,我承認(rèn)這個應(yīng)用是有點(diǎn)無趣澈吨,那么下面我們就來點(diǎn)“干貨”。

一個完整的基于Node.js的web應(yīng)用

用例

我們來把目標(biāo)設(shè)定得簡單點(diǎn)寄摆,不過也要夠?qū)嶋H才行:

用戶可以通過瀏覽器使用我們的應(yīng)用谅辣。

當(dāng)用戶請求http://domain/start時,可以看到一個歡迎頁面婶恼,頁面上有一個文件上傳的表單桑阶。

用戶可以選擇一個圖片并提交表單,隨后文件將被上傳到http://domain/upload勾邦,該頁面完成上傳后會把圖片顯示在頁面上蚣录。

差不多了,你現(xiàn)在也可以去Google一下眷篇,找點(diǎn)東西亂搞一下來完成功能萎河。但是我們現(xiàn)在先不做這個。

更進(jìn)一步地說,在完成這一目標(biāo)的過程中虐杯,我們不僅僅需要基礎(chǔ)的代碼而不管代碼是否優(yōu)雅玛歌。我們還要對此進(jìn)行抽象,來尋找一種適合構(gòu)建更為復(fù)雜的Node.js應(yīng)用的方式擎椰。

應(yīng)用不同模塊分析

我們來分解一下這個應(yīng)用支子,為了實(shí)現(xiàn)上文的用例,我們需要實(shí)現(xiàn)哪些部分呢达舒?

我們需要提供Web頁面值朋,因此需要一個HTTP服務(wù)器

對于不同的請求,根據(jù)請求的URL休弃,我們的服務(wù)器需要給予不同的響應(yīng)吞歼,因此我們需要一個路由,用于把請求對應(yīng)到請求處理程序(request handler)

當(dāng)請求被服務(wù)器接收并通過路由傳遞之后塔猾,需要可以對其進(jìn)行處理,因此我們需要最終的請求處理程序

路由還應(yīng)該能處理POST數(shù)據(jù)稽坤,并且把數(shù)據(jù)封裝成更友好的格式傳遞給請求處理入程序丈甸,因此需要請求數(shù)據(jù)處理功能

我們不僅僅要處理URL對應(yīng)的請求,還要把內(nèi)容顯示出來尿褪,這意味著我們需要一些視圖邏輯供請求處理程序使用睦擂,以便將內(nèi)容發(fā)送給用戶的瀏覽器

最后,用戶需要上傳圖片杖玲,所以我們需要上傳處理功能來處理這方面的細(xì)節(jié)

我們先來想想顿仇,使用PHP的話我們會怎么構(gòu)建這個結(jié)構(gòu)。一般來說我們會用一個Apache HTTP服務(wù)器并配上mod_php5模塊摆马。

從這個角度看臼闻,整個“接收HTTP請求并提供Web頁面”的需求根本不需要PHP來處理。

不過對Node.js來說囤采,概念完全不一樣了述呐。使用Node.js時,我們不僅僅在實(shí)現(xiàn)一個應(yīng)用蕉毯,同時還實(shí)現(xiàn)了整個HTTP服務(wù)器乓搬。事實(shí)上,我們的Web應(yīng)用以及對應(yīng)的Web服務(wù)器基本上是一樣的代虾。

聽起來好像有一大堆活要做进肯,但隨后我們會逐漸意識到,對Node.js來說這并不是什么麻煩的事棉磨。

現(xiàn)在我們就來開始實(shí)現(xiàn)之路江掩,先從第一個部分--HTTP服務(wù)器著手。

構(gòu)建應(yīng)用的模塊

一個基礎(chǔ)的HTTP服務(wù)器

當(dāng)我準(zhǔn)備開始寫我的第一個“真正的”Node.js應(yīng)用的時候,我不但不知道怎么寫Node.js代碼频敛,也不知道怎么組織這些代碼项郊。

我應(yīng)該把所有東西都放進(jìn)一個文件里嗎?網(wǎng)上有很多教程都會教你把所有的邏輯都放進(jìn)一個用Node.js寫的基礎(chǔ)HTTP服務(wù)器里斟赚。但是如果我想加入更多的內(nèi)容着降,同時還想保持代碼的可讀性呢?

實(shí)際上拗军,只要把不同功能的代碼放入不同的模塊中任洞,保持代碼分離還是相當(dāng)簡單的。

這種方法允許你擁有一個干凈的主文件(main file)发侵,你可以用Node.js執(zhí)行它交掏;同時你可以擁有干凈的模塊,它們可以被主文件和其他的模塊調(diào)用刃鳄。

那么盅弛,現(xiàn)在我們來創(chuàng)建一個用于啟動我們的應(yīng)用的主文件,和一個保存著我們的HTTP服務(wù)器代碼的模塊叔锐。

在我的印象里挪鹏,把主文件叫做index.js或多或少是個標(biāo)準(zhǔn)格式。把服務(wù)器模塊放進(jìn)叫server.js的文件里則很好理解愉烙。

讓我們先從服務(wù)器模塊開始讨盒。在你的項目的根目錄下創(chuàng)建一個叫server.js的文件,并寫入以下代碼:

var http = require("http");

http.createServer(function(request, response){

response.writeHead(200,{"Content-Type":"text/plain"});

response.write("Hello World");

response.end();

}).listen(8888);

搞定步责!你剛剛完成了一個可以工作的HTTP服務(wù)器返顺。為了證明這一點(diǎn),我們來運(yùn)行并且測試這段代碼蔓肯。首先遂鹊,用Node.js執(zhí)行你的腳本:

node server.js

接下來,打開瀏覽器訪問http://localhost:8888/省核,你會看到一個寫著“Hello World”的網(wǎng)頁稿辙。

這很有趣,不是嗎气忠?讓我們先來談?wù)凥TTP服務(wù)器的問題邻储,把如何組織項目的事情先放一邊吧,你覺得如何旧噪?我保證之后我們會解決那個問題的吨娜。

分析HTTP服務(wù)器

那么接下來,讓我們分析一下這個HTTP服務(wù)器的構(gòu)成淘钟。

第一行請求(require)Node.js自帶的http模塊宦赠,并且把它賦值給http變量。

接下來我們調(diào)用http模塊提供的函數(shù):createServer。這個函數(shù)會返回一個對象勾扭,這個對象有一個叫做listen的方法毡琉,這個方法有一個數(shù)值參數(shù),指定這個HTTP服務(wù)器監(jiān)聽的端口號妙色。

咱們暫時先不管http.createServer的括號里的那個函數(shù)定義桅滋。

我們本來可以用這樣的代碼來啟動服務(wù)器并偵聽8888端口:

var http = require("http");

var server = http.createServer();

server.listen(8888);

這段代碼只會啟動一個偵聽8888端口的服務(wù)器,它不做任何別的事情身辨,甚至連請求都不會應(yīng)答丐谋。

最有趣(而且,如果你之前習(xí)慣使用一個更加保守的語言煌珊,比如PHP号俐,它還很奇怪)的部分是createSever()的第一個參數(shù),一個函數(shù)定義定庵。

實(shí)際上吏饿,這個函數(shù)定義是createServer()的第一個也是唯一一個參數(shù)。因為在JavaScript中洗贰,函數(shù)和其他變量一樣都是可以被傳遞的找岖。

進(jìn)行函數(shù)傳遞

舉例來說,你可以這樣做:

function say(word){

console.log(word);

}

function execute(someFunction, value){

someFunction(value);

}

execute(say,"Hello");

請仔細(xì)閱讀這段代碼敛滋!在這里,我們把say函數(shù)作為execute函數(shù)的第一個變量進(jìn)行了傳遞兴革。這里返回的不是say的返回值绎晃,而是say本身!

這樣一來杂曲,say就變成了execute中的本地變量someFunction庶艾,execute可以通過調(diào)用someFunction()(帶括號的形式)來使用say函數(shù)。

當(dāng)然擎勘,因為say有一個變量咱揍,execute在調(diào)用someFunction時可以傳遞這樣一個變量。

我們可以棚饵,就像剛才那樣煤裙,用它的名字把一個函數(shù)作為變量傳遞。但是我們不一定要繞這個“先定義噪漾,再傳遞”的圈子硼砰,我們可以直接在另一個函數(shù)的括號中定義和傳遞這個函數(shù):

function execute(someFunction, value){

someFunction(value);

}

execute(function(word){ console.log(word)},"Hello");

我們在execute接受第一個參數(shù)的地方直接定義了我們準(zhǔn)備傳遞給execute的函數(shù)。

用這種方式欣硼,我們甚至不用給這個函數(shù)起名字题翰,這也是為什么它被叫做匿名函數(shù)

這是我們和我所認(rèn)為的“進(jìn)階”JavaScript的第一次親密接觸,不過我們還是得循序漸進(jìn)”希現(xiàn)在冯事,我們先接受這一點(diǎn):在JavaScript中,一個 函數(shù)可以作為另一個函數(shù)接收一個參數(shù)血公。我們可以先定義一個函數(shù)昵仅,然后傳遞,也可以在傳遞參數(shù)的地方直接定義函數(shù)坞笙。

函數(shù)傳遞是如何讓HTTP服務(wù)器工作的

帶著這些知識岩饼,我們再來看看我們簡約而不簡單的HTTP服務(wù)器:

var http = require("http");

http.createServer(function(request, response){

response.writeHead(200,{"Content-Type":"text/plain"});

response.write("Hello World");

response.end();

}).listen(8888);

現(xiàn)在它看上去應(yīng)該清晰了很多:我們向createServer函數(shù)傳遞了一個匿名函數(shù)。

用這樣的代碼也可以達(dá)到同樣的目的:

var http = require("http");

function onRequest(request, response){

response.writeHead(200,{"Content-Type":"text/plain"});

response.write("Hello World");

response.end();

}

http.createServer(onRequest).listen(8888);

也許現(xiàn)在我們該問這個問題了:我們?yōu)槭裁匆眠@種方式呢薛夜?

基于事件驅(qū)動的回調(diào)?實(shí)在太多籍茧,有興趣的朋友可點(diǎn)擊閱讀全文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市梯澜,隨后出現(xiàn)的幾起案子寞冯,更是在濱河造成了極大的恐慌,老刑警劉巖晚伙,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吮龄,死亡現(xiàn)場離奇詭異,居然都是意外死亡咆疗,警方通過查閱死者的電腦和手機(jī)漓帚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來午磁,“玉大人尝抖,你說我怎么就攤上這事⊙富剩” “怎么了昧辽?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長登颓。 經(jīng)常有香客問我搅荞,道長,這世上最難降的妖魔是什么框咙? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任咕痛,我火速辦了婚禮,結(jié)果婚禮上扁耐,老公的妹妹穿的比我還像新娘暇检。我一直安慰自己,他們只是感情好婉称,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布块仆。 她就那樣靜靜地躺著构蹬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悔据。 梳的紋絲不亂的頭發(fā)上庄敛,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機(jī)與錄音科汗,去河邊找鬼藻烤。 笑死,一個胖子當(dāng)著我的面吹牛头滔,可吹牛的內(nèi)容都是我干的怖亭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼坤检,長吁一口氣:“原來是場噩夢啊……” “哼兴猩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起早歇,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤倾芝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后箭跳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體晨另,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年谱姓,在試婚紗的時候發(fā)現(xiàn)自己被綠了借尿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡屉来,死狀恐怖垛玻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情奶躯,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布亿驾,位于F島的核電站嘹黔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏莫瞬。R本人自食惡果不足惜儡蔓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疼邀。 院中可真熱鬧喂江,春花似錦、人聲如沸旁振。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吉嚣,卻和暖如春梢薪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尝哆。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工秉撇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秋泄。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓琐馆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親恒序。 傳聞我的和親對象是個殘疾皇子瘦麸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Node.js是目前非常火熱的技術(shù)奸焙,但是它的誕生經(jīng)歷卻很奇特瞎暑。 眾所周知,在Netscape設(shè)計出JavaScri...
    w_zhuan閱讀 3,613評論 2 41
  • Node.js是目前非秤敕火熱的技術(shù)了赌,但是它的誕生經(jīng)歷卻很奇特。 眾所周知玄糟,在Netscape設(shè)計出JavaScri...
    Myselfyan閱讀 4,072評論 2 58
  • https://nodejs.org/api/documentation.html 工具模塊 Assert 測試 ...
    KeKeMars閱讀 6,331評論 0 6
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理勿她,服務(wù)發(fā)現(xiàn),斷路器阵翎,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • 日總結(jié)20170811:玫瑰原義玫:在玉石上刻繪美麗的花紋瑰:難以描述的美麗的玉石寫法玫?斜玉旁逢并, 以豎1線為中心...
    月諾兮閱讀 182評論 0 0