最近在學習NodeJs。從nodejs語言本身,看了朴靈的《深入淺出NodeJs》,《Node即學即用》。個人感覺朴靈的這本書適合node入門后乃至中級程序員去閱讀。而后者則可以完全當做初級入門教材使用。當然我認為最快捷的學習路徑是看視頻。這里推薦 慕課網的node視頻,講的還是非常不錯的。雖然說nodej是Javascript在服務端的一種表現,嚴格來說算不上說是一種新的語言。連官方也說,其強大的性能來源於google的v8引擎。換句話說,以前Javascript在客戶端的瀏覽器里運行。PC機器為瀏覽器預留了一大塊內存空間,在瀏覽器建立了一個JavaScript解釋器,也就是V8引擎。只是Ryna Dahl把這個引擎移動到了服務端。
了解完這個這個前提之后,就能揭開NodeJs的神秘面紗了。至於NodeJs於JavaScript在表現上有何異同,大家可以去參考相對基礎的文章去了解基礎知識。如果JavaScript還不太了解,還是建議閱讀《JavaScript權威指南》(犀牛書雖然特別大部頭,但是讀起來特別爽快,就好像Javascipt大牛跟你面對面交流似得,好像他就知道你這里不懂,真是貼心到想哭)。學完了nodejs和一些核心包,以及數據庫框架,終於准備動手做一些東西了。在做的過程中也對nodejs有了更深的了解,其中最大的坑也就是nodejs的異步執行,這也是nodejs的最大特點。后來了解到Promise這個Es6的新特性。可以讓代碼的流程執行的更加清晰明了。
推薦http://www.cnblogs.com/lvdabao/p/es6-promise-1.html
下面是使用nodejs抓取博客園前10頁所有的文章標題和文章對應的鏈接。代碼中有詳細注釋,有問題的可以評論區討論。
1 var http = require('http'); //引入nodejs的http模塊,該模塊用於構建http服務和作為HttpClient使用。 2 var promise = require('promise'); //對異步編程進行流程控制,更加符合后端程序員的編程習慣。 3 var cheerio = require('cheerio'); //可以理解為服務端的Jquery。使用方法和客戶端一樣。 4 5 var url = 'http://www.cnblogs.com/#p'; //要抓取的網址。博客園的頁數是通過添加錨點的,后面有拼接 6 7 8 //Promise 在任何情況下都處於以下三種狀態中的一種: 9 //未完成(unfulfilled)、已完成(resolved)和拒絕(rejected) 10 //事件已完成則使用成功的callback(resolve)返回自身,失敗了則 11 //選擇使用callback(reject)來返回失敗的自身。 12 13 function getPageList(url){ 14 //return Promise對象 15 return new Promise(function(resolve,reject) { 16 http.get(url,function(res) { 17 var body = ''; 18 19 //當接受到數據的時候,http是執行范圍請求的。所以每個范圍請求就是一個chunk。 20 res.on('data', function(chunk) { 21 //buffer是一種node處理二進制信息的格式,不必理會。 22 res.setEncoding('utf8'); //設置buffer字符集 23 body += chunk; //拼接buffer 24 }); 25 26 //當整個http請求結束的時候 27 res.on('end', function() { 28 var $ = cheerio.load(body); //將html變為jquery對象。 29 var articleList = $('.post_item'); 30 var articleArr = []; 31 articleList.each(function() { 32 var curEle = $(this); 33 var title = curEle.find('.post_item_body h3').text(); //獲取標題 34 var href = curEle.find('.post_item_body h3 a').attr('href'); //文章鏈接 35 articleArr.push({ 36 title:title, 37 href:href 38 }); 39 40 41 }); 42 43 //成功的狀態使用resolve回調函數。 44 resolve(articleArr); 45 46 }); 47 48 //當執行http請求失敗的時候,返回錯誤信息 49 res.on('error', function(e) { 50 reject(e.message); 51 }); 52 53 54 55 }) 56 }) 57 } 58 59 60 //請求博客園前10頁的數據。將所有的請求預先放置在集合內。 61 var list = []; 62 for(var i=1;i<=10;i++) { 63 var url = url+i; 64 list.push(getPageList(url)); 65 66 } 67 68 //調用Promise的下面的all方法。參數是一個事件集合。 69 //Promise將會進行異步執行。但是最后的返回時機要根據最耗時的那個請求為標准。 70 //then(),可以接受兩個參數(callback).第一個參數是成功(resolved)的回調。 71 //第二個參數是執行上個操作失敗(rejected)的回調。 72 Promise 73 .all(list) 74 .then(function(data) { 75 console.dir(data); 76 })
以下是結果:
此前工作繁忙,這段時間空下來了。從今天起,將會陸續介紹nodejs或者是其他方面的東西。