進擊Node.js基礎(一)

一.NodeJS基本介紹javascript

1.Node-Webkit、appjs:容許開發者使用Web技術,html/css來開發跨平臺的桌面應用程序,能兼容mac、Linux、Windows
2.Jade:和NodeJS組合使用,能夠高效的管理後臺html模板
3.Ghost:是一個強大且體驗超好的開源博客程序
4.Grunt:是javascript跑各類任務的運行工具,經過集成各類插件來完成好比樣式編譯、腳本檢查、腳本壓縮合並、自動化測試、Shell腳本運行、文檔生成,甚至是圖片處理等等各類各樣的任務。
5.gulp:針對grunt的複雜配置有了更簡潔高效的組織方式
6.Express.js:基於Node.js 平臺,快速、開放、極簡的 web 開發框架
7.Nodecast:先是在PC端運行它,而後啓動移動設備,選擇一個支持Nodecast的應用程序,而後就能夠把移動廣播中的內容映射到電腦上,等於把電腦當一個流媒體來使用
8.Log.io:讓你在瀏覽器裏面能夠實時地監控項目日誌
9.PDFKit:用來生成PDF文檔
10.Haroopad:是一個Linux上的markdown編輯器
11.NoduinoWeb:硬件黑客但願經過Noduino Web頁面來控制開源硬件,從而將軟件和硬件很好的結合起來
12.NodeOS:是一款基於Node.js的開發的友好的操做系統

二.學習NodeJS推薦四個網站
1.nodejs.org,官網
2.www.npmjs.com,模塊社區搜索對應的模塊,參加別人代碼是如何組織的
3.github.com,閱讀優秀的源碼
4.stackoverflow.com,技術問答社區css

 

三.Node.js的版本
偶數位爲穩定的版本 -0.6.x,-0.8.x,-0.10.x
奇數位爲非穩定的版本 -0.7.x,-0.9.x,-0.11.xhtml

 

四.Windows上安裝git bash
一路下一步安裝完畢java

 

五.安裝nodejs
https://nodejs.org/下載nodejs安裝成功後,會自動在環境變量的Path中添加nodejs的安裝路徑node

運行環境:以下是在Chrome瀏覽器上運行js和在Node.js中運行jsgit

第一個實例:server.jsgithub

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello Node.js\n');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

  在git bash上進入server.js所在的目錄,輸入node server.jsweb

  而後在瀏覽器中輸入:http://127.0.0.1:3000/,運行效果以下:chrome

 

六.模塊與包管理工具數據庫

 

實例:

teacher.js

function add(teacher) {
    console.log('Add Teacher:' + teacher)
}

exports.add = add

student.js

function add(student) {
    console.log('Add Student:' + student)
}

exports.add = add

klass.js

var student = require('./student.js')
var teacher = require('./teacher.js')

function add(teacherName, students) {
    teacher.add(teacherName)

    students.forEach(function(item, index) {
        student.add(item)
    })
}

//傳統的模塊實例,exports是module的一個輔助方法,推薦這種方式
exports.add = add
//實例成爲特殊的模塊類型,真實存在的東西,返回調用者exports掛載的屬性和方法賦給module.exports
//若是module.exports存在屬性和方法,則被忽略
//module.exports = add

index.js

var klass = require('./klass')

klass.add('Scott', ['白富美','高富帥'])

exports.add = function(klasses) {
    klasses.forEach(function(item, index) {
        var _klass = item
        var teacherName = item.teacherName
        var students = item.students
        klass.add(teacherName, students)
    })
}

 

七.Node.js API
  分化爲node.js、io.js兩個陣營

 

八.URL網址解析的好幫手

url.parse('http://imooc.com/course/list')
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'imooc.com',
  port: null,
  hostname: 'imooc.com',
  hash: null,
  search: null,
  query: null,
  pathname: '/course/list',
  path: '/course/list',
  href: 'http://imooc.com/course/list' }
> url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor!')
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'imooc.com:8080',
  port: '8080',
  hostname: 'imooc.com',
  hash: '#floor!',
  search: '?from=scott&course=node',
  query: 'from=scott&course=node',
  pathname: '/course/list',
  path: '/course/list?from=scott&course=node',
  href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor!' }
> url.format({
...   protocol: 'http:',
...   slashes: true,
...   auth: null,
...   host: 'imooc.com:8080',
...   port: '8080',
...   hostname: 'imooc.com',
...   hash: '#floor!',
...   search: '?from=scott&course=node',
...   query: 'from=scott&course=node',
...   pathname: '/course/list',
...   path: '/course/list?from=scott&course=node',
...   href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor!' }
... )
'http://imooc.com:8080/course/list?from=scott&course=node#floor!'
> url.resolve('http://imooc.com/','/course/list')
'http://imooc.com/course/list'
> url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor1')
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'imooc.com:8080',
  port: '8080',
  hostname: 'imooc.com',
  hash: '#floor1',
  search: '?from=scott&course=node',
  query: 'from=scott&course=node',
  pathname: '/course/list',
  path: '/course/list?from=scott&course=node',
  href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor1' }
> url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor1', t
rue)
Url {
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'imooc.com:8080',
  port: '8080',
  hostname: 'imooc.com',
  hash: '#floor1',
  search: '?from=scott&course=node',
  query: { from: 'scott', course: 'node' },
  pathname: '/course/list',
  path: '/course/list?from=scott&course=node',
  href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor1' }
> url.parse('//imooc.com/course/list',true)
Url {
  protocol: null,
  slashes: null,
  auth: null,
  host: null,
  port: null,
  hostname: null,
  hash: null,
  search: null,
  query: {},
  pathname: '//imooc.com/course/list',
  path: '//imooc.com/course/list',
  href: '//imooc.com/course/list' }
> url.parse('//imooc.com/course/list',true,true)
Url {
  protocol: null,
  slashes: true,
  auth: null,
  host: 'imooc.com',
  port: null,
  hostname: 'imooc.com',
  hash: null,
  search: null,
  query: {},
  pathname: '/course/list',
  path: '/course/list',
  href: '//imooc.com/course/list' }
>

 

九.QueryString參數處理小利器

> querystring.stringify({name:'scott', course:['jade','node'], from:''})
'name=scott&course=jade&course=node&from='
> querystring.stringify({name:'scott', course:['jade','node'], from:''}, ',')
'name=scott,course=jade,course=node,from='
> querystring.stringify({name:'scott', course:['jade','node'], from:''}, ',', ':')
'name:scott,course:jade,course:node,from:'
> querystring.parse('name=scott&course=jade&course=node&from=')
{ name: 'scott', course: [ 'jade', 'node' ], from: '' }
> querystring.parse('name=scott,course=jade,course=node,from=', ',')
{ name: 'scott', course: [ 'jade', 'node' ], from: '' }
> querystring.parse('name=scott,course=jade,course=node,from=')
{ name: 'scott,course=jade,course=node,from=' }
> querystring.parse('name=scott,course=jade,course=node,from=', ',', '=')
{ name: 'scott', course: [ 'jade', 'node' ], from: '' }

> querystring.escape('<哈哈>')
'%3C%E5%93%88%E5%93%88%3E'
> querystring.unescape('%3C%E5%93%88%E5%93%88%3E')
'<哈哈>'

 

十.HTTP知識先填坑
  http客戶端發起請求,建立端口
  http服務器在端口監聽客戶端請求
  http服務器向客戶端返回狀態和內容

  當輸入網址回車,頁面就出來了,但計算機和瀏覽器作了許許多多的事情:
1.Chrome搜索自身的DNS緩存
  瀏覽器上輸入:chrome://net-internals/#dns,就能夠查看曾經瀏覽過的網站的DNS緩存記錄

2.搜索操做系統自身的DNS緩存(瀏覽器沒有找到緩存或緩存已經失效)

  如瀏覽器沒有找到緩存或已失效,則搜索操做系統自身的DNS緩存,如找到且沒有過時,則會中止搜索,解析到此結束

3.讀取本地的HOST文件
如操做系統的dns緩存也沒有找到,則會去讀本地的host文件,如windows是在C:\Windows\System32\drivers\etc目錄下。
4.瀏覽器發起一個DNS的一個系統調用
 若是在本地的host文件中也沒有找到對應的配置項,瀏覽器就會發起一個DNS的一個系統調用,向本地主控dns服務器(是你的寬帶運營商提供的)發起一個域名解析請
求,運營商的dns服務器具體會作以下事情:
 a.寬帶運營商服務器查看自己緩存
 b.運營商服務器發起一個迭代dns解析的請求(實際步驟可能比這複雜)
  嘿,哥們imooc.com的域名地址是多少?
我只知道com域的項級域的ip地址
  運營商主控dns服務器就找到com域的服務器,向項級域的ip地址服務器詢問imooc.com的域名地址是多少
  我只知道imooc.com域的IP地址
  運營商主控dns服務器就找到imooc.com域的dns服務器,這個通常是域名的註冊商提供的,而後問它imooc.com域的ip地址是多少
  imooc.com域的dns服務器一查,查然在我這,而後把它查到的結果發送給運營商的dns服務器
  運營商服務器把結果返回操做系統內核同時緩存起來
  操做系統內核把結果返回瀏覽器
  最終瀏覽器拿到了www.imooc.com對應的IP地址
5.瀏覽器得到域名對應的IP地址後,發起HTTP「三次握手」
  瀏覽器會以一個隨機端口向服務器的web程序(如http的80端口)發起TCP鏈接請求,這個鏈接請求經過層層路由設備到達服務器後進入到網卡,而後進入到內核的TCP/IP協議棧,還有可能要通過防火牆的過濾,最終到達web服務端,而後創建起tcp/ip的鏈接。
  「三次握手」過程:
  a.客戶端對服務器說:哥們,能聽到我說話嗎?嘮嘮唄
  b.服務器就對客戶端說:兄弟,我能聽到你說話,咱嘮嘮
  c.客戶端再對服務器說:好的哥們,咱倆開嘮吧
6.TCP/IP鏈接創建起來後,瀏覽器就能夠向服務器發送HTTP請求了,使用了好比說,用HTTP的GET方法請求一個根域裏的一個域名,協議能夠採HTTP1.0的一個協議
7.服務器端接受到了這個請求,根據路徑參數,通過後端的一些處理以後,把處理後的一個結果的數據返回給瀏覽器,若是是慕課網的頁面就會把完整的HTML頁面代碼返
回給瀏覽器
8.瀏覽器拿到了慕課網的完整的HTML頁面代碼,在解析和渲染這個頁面的時候,裏面的JS、CSS、圖片靜態資源,他們一樣也是一個個HTTP請求都須要通過上面的主要的
七個步驟
9.瀏覽器根據拿到的資源對頁面進行渲染,最終把一個完整的頁面呈現給了用戶

 

十一.HTTP請求的流程拆分開,拆分紅請求和響應,不管請求仍是響應,都會發送http頭和正文信息
  HTTP頭髮送的是一些附加的信息:內容類型、服務器發送響應的日期、HTTP狀態碼,正文就是用戶提交的表單數據。

 

十二.Chrome瀏覽器F12查看HTTP請求
1.Timing:圖形化顯示這個請求加裁過程當中每一個階段所要耗費的時間
  a.Stalled:瀏覽器要發出這個請求到這個請求能夠發出的這個等待時間,通常是代理協商、配置的pk腳本、等待可複用的TCP鏈接釋放的時間,不包含查詢和創建TCP連
接的時間
  b.Proxy negotiation:代理協商的時間
  c.Reuqest/Response
    Request sent:請求的第一個字節發出之前到最後一個字節發出後的時間,能夠理解爲請求時間或上傳時間
    Waiting(TTFB):請求發出之後到收到響應的第一個字節所花費的時間,這個包括整個數據在各個路由中貫穿中所延遲的時間,以及服務器端要響應這個請求所作的後臺的一些處理,能夠看到這個所耗費的時間最長,尤爲是咱們有大文件上傳時會更慢
    Content Download:收到響應的第一個字節開始,到接收完最後一個字節所花費的時間,也就是下載時間
經過分析這個Timing,或者根據以前頁面歷史上數據的對比,就能夠找到一些頁面慢,以及慢的瓶頸在哪。
2.Headers
  1)和請求有關
  a.Remote Address:遠端服務器的IP地址
  b.Request URL:請求地址
  c.Request Method:請求方法
  d.Request Headers:請求頭
  2)和響應有關
  a.Status Code:響應狀態碼
  b.Response Headers:響應頭

 

十三.HTTP請求方法
  HTTP1.1協議中定義了八種方法(或叫動做)
  GET:獲取數據
  POST:向指定的資源提交數據,如要新建一個用戶、上傳一個視頻
  PUT:更新,向指定的資源上傳一個最新內容,如更新已有用戶的頭像,替換一個已有的視頻
  DELETE:刪除,請求服務器刪除咱們標識的某個資源
  HEAD:和GET同樣,都是向服務器發出指定資源的一個請求,只不過服務器它不傳回資源的本文的部分,它的好處是不用傳輸所有的內容就能夠獲取裏面的原信息或原數

  CONNECT:HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器
  TRACE:回顯服務器收到的請求,主要用於測試或診斷
  OPTIONS:容許客戶端查看服務器的性能

 

十四.HTTP請求的狀態碼
瀏覽器返回給瀏覽器時,告之瀏覽器我當前的請求成功或失敗的一個指示信息的狀態,通常三個數字組成,第一個數字定義響應的類別。
  1XX:給示請求已經接收,繼續處理
  2XX:表示成功,請求已成功的接收並處理掉了
  3XX:重定向,表示要完成這個請求必需要進行更進一步的操做
  4XX:客戶端錯誤,請求時有誤法錯誤或者這個請求沒法實現
  5XX:服務端錯誤,服務器不能實現這個合法的請求
如常見的狀態碼
  200:OK,說明客戶端請求成功
  400:客戶端請求有語法錯誤,服務器端不能理解
  401:請求未通過受權
  403:服務端收到這個請求,可是拒絕提供服務,可能仍是沒有權限等等
  404:沒找到,請求資源不存在或者是你輸錯了URL地址
  500:服務器端發生了不可預期的錯誤
  503:服務器當前還不能處理當前的這個請求,可能須要過一段時間以後才能恢復正常

 

十五.HTTP事件回調進階
  HTTP模塊有考慮支持不少HTTP協議的特性,這些特性在傳統開發中確很難使用,好比大致積的擴編碼的消息,除此以外,爲了讓用戶能夠在請求和響應中使用流的形式操做數據,
接口從不緩存整個請求或者響應,整個HTTP API都很底層,它只處理流相關的操做以及信息解析,能夠把信息解析成請求頭、請求體,但並不去解析實際的請求頭和請求正文裏面的具體內容。
1.HTTP概念進階
a.什麼是回調?
  異步編程最基本的方法,需按順序執行異步邏輯時,通常採用後續傳遞的方法。也就是將後續邏輯封裝在回調函數中作爲起始函數的參數層層嵌套,經過這種方式來讓程序按照咱們所指望的方式走完整個流程。

callback.js

function learn(something) {
    console.log(something)
}

function we(callback, something) {
    something += ' is cool'
    callback(something)
}

we(learn, 'Nodejs')

we(function(something) {
    console.log(something)
}, 'Jade')

 b.什麼是同步/異步?

  同步就是執行一個任務,後面一個任務等待前一個任務結束。
  每一個任務有一個或多個回調函數

async.js

var c = 0

function printIt() {
    console.log(c)
}

function plus() {
    setTimeout(function() {
        c += 1
    }, 1000)
}

plus()
printIt()

async2.js

var c = 0

function printIt() {
    console.log(c)
}

function plus(callback) {
    setTimeout(function() {
        c += 1
        callback()
    }, 1000)
}

plus(printIt)

c.什麼是I/O?
  磁盤的寫入和讀出,爲文件系統、數據庫資料提供接口,向文件系統發送請求時,不用等到硬盤,硬盤準備好了,非阻塞接口會通知到Node
d.什麼是單線程/多線程?
  單線程代碼是按順序執行的,多線程代碼
e.什麼是阻塞/非阻塞
f.什麼是事件?
  鼠標點擊、拖拽窗口都是事件
g.什麼是事件驅動?

event.js

function clickIt(e) {
    window.alert('Button is cliecked')
}

var button = document.getElementById('#button')
button.addEventListener('click', clickIt)

  這幾行代碼就能實現當按鈕被點擊時就能觸發一個回調函數,就是這個clickIt,彈出一個框

  全部能觸發事件的對象,都是Event下面的EventEmitter的實例
  爲了某個事件註冊函數,像這個函數不是立刻執行,只有當事件發生時纔會調用回調函數,這種函數執行的方式就叫作事件驅動。
h.什麼是基於事件驅動的回調?
  這種註冊回調就是基於事件驅動的回調,若是這些回調和異步IO操做有關,則就能夠看做是基於回調的異步IO,只不過這種回調是在Node.js裏面是由事件來驅動的。
i.什麼是事件循環?
  若是有大量的異步操做,以及IO的耗時操做,甚至是一些定時器控制的延時操做,它們完成時都要去調用相應的回調函數,從而來完成一些密集的任務,而又不會阻塞整個程序執行的流程,那這個時候,這麼多事件就須要一個機制來管理,這種機制就是事件循環。
  EventLoop是一個回調函數隊列,當異步函數執行的時候,回調函數就會被壓入到這人隊列,對Node.js來講,靠一個單線程不斷地查詢隊列中是否有事件,當它讀取到一個事件時,將調用與這個事件關聯的javaScript函數。
  事件循環是一個先進先出的任務隊列,回調就按照它們被加入的順序來執行。整個隊列能夠理解成普通函數和回調函數構成的一個完整的隊列。

 

十六.HTTP源碼解讀
1.什麼是做用域?
  做用域和調用函數訪問變量的能力有關
  分:局部做用域和全局做用域

scope.js

var globalVariable = 'This is global variable'

function globalFunction() {
    var localVariable = 'This is local variable'

    console.log('Visit global/local variable')
    console.log(globalVariable)
    console.log(localVariable)

    globalVariable = 'This is changed variable'
    console.log(globalVariable)

    function localFunction() {
        var innerLocalVariable = 'This is inner local variable'

        console.log('Visit global/local/innerLocal variable')
        console.log(globalVariable)
        console.log(localVariable)
        console.log(innerLocalVariable)
    }

    localFunction()
}

globalFunction()

運行結果:


2.什麼是上下文?

context.js

var pet = {
    words: '...',
    speak: function() {
        console.log(this.words)
        console.log(this === pet)
    }
}

pet.speak()

運行結果:

context02.js

function pet(words) {
    this.words = words
    console.log(this.words)
    console.log(this === global)
}

//這裏調pet方法,調用這個方法的對象並非pet自身,而是頂層的global對象
pet('...')

運行結果:

context03.js

function Pet(words) {
    this.words = words
    this.speak = function() {
        console.log(this.words)
        console.log(this)
    }
}

var cat = new Pet('Miao')

cat.speak()

運行結果:

經過以上三段代碼,咱們來理解一下上下文:

  this關鍵字有關,是調當前可執行代碼的引用

  在js裏面,this關鍵字一般是指向當前函數的擁有者,一般把擁有者叫作執行上下文。
  this是JS語言的一個關鍵字,表明函數運行時自動生成的一個內部對象,只能在函數內部使用。
  同時,對於函數的上下文執行對象,須要依據當前的運行環境而定,由於上下文執行對象在程序運行時來肯定,也能夠動態去改變。
  在全局運行的上下文中,this指向的是全局對象,在函數內部,this取決於函數被調用的方式,被調用的方式主要有:
  a.做爲對象的方法,pet.speak(),裏面的this指向的對象就是pet這個對象
  b.直接函數調用,這時內部的this指向的是全局對象
  c.在構造函數中使用this,那這個this就指向到新構建好的對象,就是實例對象。
  JS的上下文存在一個定義時的上下文和運行時的上下文以及上下文能夠改變的。
  使用call和apply能夠改變上下文執行對象,可讓你在自定義上下文中執行函數,做用同樣,用法有區別。call函數須要一個參數列表,apply容許傳遞一個參數作爲數組。做用是調用一個對象的方法,利用另外一個對象替換當前對象,其實就是更改對象this指向的內容。說的標準點就是,以某個方法當作指定的某個對象的方法來執行。

call_apply.js

var pet = {
    words: '...',
    speak: function(say) {
        console.log(say + ' ' + this.words)
    }
}

//pet.speak('Speak')  //Speak ...

var dog = {
    words: 'Wang'
}

//在調某個方法時,指定dog這個對象爲上下文,利用這種用法,也很方便實現繼承
pet.speak.call(dog, 'Speak') //Speak Wang

運行結果:

call_apply_extend.js

function Pet(words) {
    this.words = words
    this.speak = function() {
        console.log(this.words)
    }
}

function Dog(words) {
    Pet.call(this, words)
    //Pet.apply(this, arguments)
}

var dog = new Dog('Wang')
dog.speak()

運行結果:

 

3.HTTP源碼解讀

    帶着問題看代碼。

 

十七.HTTP性能小測試
1.Apache ab
  在命行裏輸入:ab -n1000 -c10 http://localhost:3000/
  -n1000:總的請求數是1000,默認是1
  -c10:併發數是10,默認是1
  -t:用來測試進行的總時間
  -p:post時的數據文件
  -w:以html表格格式輸出結果
2.ab -n1000 -c10 http://www.imooc.com/
  慕課網性能小測試

 

十八.HTTP爬蟲
  藉助HTTP API,使用cheerio抓取網頁數據,npm install cheerio
imooc-crawler.js

var http = require('http')
var url = 'http://www.imooc.com/learn/348'

http.get(url, function(res) {
    var html = ''
    res.on('data', function(data) {
        html += data
    })

    res.on('end', function() {
        console.log(html)
    })
}).on('error', function() {
    console.log('獲取課程數據出錯!')
})

運行結果:

crawler.js

var http = require('http')
var cheerio = require('cheerio')
var url = 'http://www.imooc.com/learn/348'

function filterChapters(html) {
    var $ = cheerio.load(html)

    var chapters = $('.learnchapter')
    var courseData = []

    chapters.each(function(item) {
        var chapter = $(this)
        var charterTitle = chapter.find('strong').text()
        var videos = chapter.find('.video').children('li')
        var chapterData = {
            chapterTitle: chapterTitle,
            videos : []
        }

        videos.each(function(item) {
            var video = $(this).find('.studyvideo')
            var videoTitle = video.text()
            var id = video.attr('href').split('video/')[1]

            chapterData.videos.push({
                title: videoTitle,
                id: id
            })
        })

        courseData.push(chapterData)
    })
    return courseData;
}

function printCourseInfo(courseData) {
    courseData.forEach(function(item) {
        var chapterTitle = item.chapterTitle

        console.log(charterTitle + '\n')

        item.videos.forEach(function(video) {
            console.log(' [' + video.id + ']' + video.title  + '\n')
        })
    })
}

http.get(url, function(res) {
    var html = ''
    res.on('data', function(data) {
        html += data
    })

    res.on('end', function() {
        var courseData = filterChapters(html)
        printCourseInfo(courseData)
    })
}).on('error', function() {
    console.log('獲取課程數據出錯!')
})

運行結果:

 

十九.事件模塊小插曲

  event emit能夠爲某個事件添加最多10個監聽函數。
  官方建議對一個事件不要設置超過10個監聽器,太多會致使內存泄露。

events.js

var EventEmitter = require('events').EventEmitter

var life = new EventEmitter()
life.setMaxListeners(11)

//也可用addEventListener

function water(who) {
    console.log('給 ' + who + ' 倒水')
}

life.on('求安慰', water)

life.on('求安慰', function(who) {
    console.log('給 ' + who + ' 揉肩')
})

life.on('求安慰', function(who) {
    console.log('給 ' + who + ' 作飯')
})

life.on('求安慰', function(who) {
    console.log('給 ' + who + ' 洗衣服')
})

life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...5')
})

life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...6')
})
life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...7')
})
life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...8')
})
life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...9')
})
life.on('求安慰', function(who) {
    console.log('給 ' + who + ' ...10')
})
life.on('求安慰', function(who) {
    console.log('給 ' + who + ' 你想累死我啊')
})

life.on('求溺愛', function(who) {
    console.log('給 ' + who + ' 買衣服')
})
life.on('求溺愛', function(who) {
    console.log('給 ' + who + ' 交工資')
})

life.removeListener('求安慰', water)
//life.removeAllListeners()
life.removeAllListeners('求安慰')

var hasConfortListener = life.emit('求安慰', '漢子')
var hasLovedListener = life.emit('求溺愛', '妹子')
var hasPlayedListener = life.emit('求玩壞', '妹子和漢子')

console.log(life.listeners('求安慰').length)
//console.log(EventEmitter.listenerCount(life, '求安慰'))
console.log(life.listeners('求溺愛').length)

console.log(hasConfortListener) //true
console.log(hasLovedListener) //true
console.log(hasPlayedListener) //false

運行結果:

 

二十.Node.js request方法
  HTTP get/request
  get是對request一個封裝,get能作的事,request都能作。
  http.request(options[,callback])
  host,path,hostname,headers,port,auth,localAddress,agent,socketPath,keepAlive,method,keepAliveMsecs

 comment.js

var http = require('http')
var querystring = require('querystring')

var postData = querystring.stringify({
    'content': '入門值得學',
    'cid': 28127
})

var options = {
    hostname: 'www.imooc.com',
    port: 80,
    path: '/course/docomment',
    method: 'POST',
    headers : {
        'Accept':'application/json, text/javascript, */*; q=0.01',
        'Accept-Encoding':'gzip, deflate, br',
        'Accept-Language':'zh-CN,zh;q=0.8',
        'Connection':'keep-alive',
        'Content-Length':postData.length,
        'Cookie':'imooc_uuid=8875f7de-e6a9-455a-8470-aac8e6c20484; imooc_isnew_ct=1502349861; PHPSESSID=547ntneegkk456214a3eiso846; loginstate=1; apsid=Y0YmZkYjg5YmU3OTMzZjI5Njg2YTE4ODcxMzU1ZTMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjc0MjIyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABiaWppYW4wMzA2QDEyNi5jb20AAAAAAAAAAAAAAAAAADBmMTk2MTlkNGM3ZDJiMjI2NDc4ODJiOTRiZWMyZWEyjXDgWsvtoFY%3DN2; IMCDNS=0; Hm_lvt_f0cfcccd7b1393990c78efdeebff3968=1524151421,1524375330,1524657829,1524667446; Hm_lpvt_f0cfcccd7b1393990c78efdeebff3968=1525408676; imooc_isnew=2; cvde=5ad894ba8e870-239',
        'Host':'www.imooc.com',
        'Origin':'https://www.imooc.com',
        'Referer':'https://www.imooc.com/u/274222',
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36',
        'X-Requested-With':'XMLHttpRequest'
    }
}

var req = http.request(options, function(res) {
    console.log('Status:' + res.statusCode)
    console.log('headers:' + JSON.stringify(res.headers))

    res.on('data', function(chunk) {
        console.log(Buffer.isBuffer(chunk))
        console.log(typeof chunk)
    })

    res.on('end', function() {
        console.log('評論完畢!')
    })
})

req.on('error', function(e) {
    console.log('Error:' + e.message)
})

req.write(postData)
req.end()

運行結果:

刷新www.imooc.com/comment/348,就能看到有剛經過代碼進行的評論。

 

學習視頻《進擊Node.js基礎(一)

相關文章
相關標籤/搜索