websocket
http是一個(gè)請求铛碑、必須有一個(gè)響應(yīng),http1.1中keepalive后也是一個(gè)tcp可以發(fā)多次請求汽烦,但還是一個(gè)請求配一個(gè)響應(yīng)
websocket協(xié)議莉御,讓瀏覽器實(shí)現(xiàn)了實(shí)時(shí)雙向通信,不一定要客戶端發(fā)起請求礁叔,服務(wù)端可以直接向客戶端發(fā)送消息
websocket和http一樣是應(yīng)用層協(xié)議,仍然是基于TCP傳輸協(xié)議煮岁,并復(fù)用HTTP的握手通道
主要的方法:onopen涣易、onmessage、onerror新症、onclose四個(gè)方法。
建立連接
首先先發(fā)送一個(gè)協(xié)議升級請求荚醒,使用的是HTTP協(xié)議隆嗅,只支持get
GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade // 表示要升級
Upgrade: websocket // 要升級成的協(xié)議
Sec-WebSocket-Version: 13 // websocket的版本
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==
服務(wù)端響應(yīng):
HTTP/1.1 101 Switching Protocols // 101表示協(xié)議還沒結(jié)束,還有其他過程
Connection:Upgrade // 表示已經(jīng)升級胖喳,之后協(xié)議都按ws協(xié)議走
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=
node
node是v8的一個(gè)執(zhí)行環(huán)境嗎,能讓js在服務(wù)端運(yùn)行精续,不能使用DOM粹懒、BOM
異步非阻塞IO
異步表示請求發(fā)出去會立即返回,通過回調(diào)函數(shù)來返回凫乖。
阻塞表示這個(gè)操作會阻塞后面的執(zhí)行弓颈,比如讀個(gè)文件就需要一直等删掀。
Node在處理高并發(fā),I/O密集場景有明顯的性能優(yōu)勢
高并發(fā): 是指在同一時(shí)間并發(fā)訪問服務(wù)器
I/O密集: 指的是文件操作、網(wǎng)絡(luò)操作纤子、數(shù)據(jù)庫
CPU密集: 指的是邏輯處理運(yùn)算款票、壓縮控硼、解壓艾少、加密、解密
node事件循環(huán)
本階段執(zhí)行已經(jīng)被 setTimeout() 和 setInterval() 的調(diào)度回調(diào)函數(shù)幔妨。
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
| 執(zhí)行延遲到下一個(gè)循環(huán)迭代的 I/O 回調(diào)谍椅。
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
| 僅系統(tǒng)內(nèi)部使用。
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘
| 檢索新的I/O事件;執(zhí)行與 I/O相關(guān)的回調(diào) ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ setImmediate() 回調(diào)函數(shù)在這里執(zhí)行埂伦。 └───────────────┘
│ ┌─────────────┴─────────────┐
│ │ check │
│ └─────────────┬─────────────┘
| 一些關(guān)閉的回調(diào)函數(shù)
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
poll階段
poll階段首先會處理 poll 隊(duì)列的事件:如fs
事件循環(huán)將同步執(zhí)行 poll 隊(duì)列里的回調(diào)思恐,直到隊(duì)列為空或執(zhí)行的回調(diào)達(dá)到系統(tǒng)上限。如果沒有其他階段的事要處理胀莹,事件循環(huán)將會一直阻塞在這個(gè)階段,等待新的 I/O 事件加入 poll 隊(duì)列中媳否。
如果其他階段出現(xiàn)了事件荆秦,則有以下情況:
1、如果 check 隊(duì)列已經(jīng)被 setImmediate 設(shè)定了回調(diào), 事件循環(huán)將結(jié)束 poll 階段往下進(jìn)入 check 階段來執(zhí)行 check 隊(duì)列(里面的回調(diào) callback)步绸。
2、如果 timers 隊(duì)列有到時(shí)的 setTimeout 或者 setInterval 回調(diào)吕喘,則事件循環(huán)將往上繞回 timers 階段,并執(zhí)行 timer 隊(duì)列
setTimeout(() => {
console.log('setTimeout')
})
setImmediate(() => {
console.log('setImmediate')
})
// 輸出結(jié)果:
// 不確定氯质,setTimeout 和 setImmediate 無法確定進(jìn)入時(shí)機(jī), 系統(tǒng)執(zhí)行快了setTimeout先,系統(tǒng)慢了setImmediate先拱礁。
fs.readFile('file.path', (err, file) => {
setTimeout(() => {
console.log('setTimeout')
})
setImmediate(() => {
console.log('setImmediate')
})
})
// 輸出結(jié)果:setImmediate setTimeout
// poll階段執(zhí)行readFile蜓陌,然后隊(duì)列清空后先去執(zhí)行check階段,完了再走timer階段
微任務(wù)會穿插在各個(gè)階段中執(zhí)行
不管再任何地方調(diào)用钮热,只要有微任務(wù)就會執(zhí)行烛芬,并且nextTick優(yōu)先級比promise高
express和koa區(qū)別
1赘娄、express使用回調(diào)函數(shù)仆潮、koa中使用的是async和await
2遣臼、中間件區(qū)別,express會從頭到尾走一波鹏浅,不斷調(diào)用next找下一個(gè)中間件屏歹,koa是洋蔥圈。