本節(jié)我們將簡(jiǎn)單介紹一下 koa扇谣。
nodejs是什么蹈胡?
Node.js是一個(gè)創(chuàng)建于 2009年的Javascript運(yùn)行環(huán)境通熄。它使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式 I/O 的模型脱羡,基于回調(diào)實(shí)現(xiàn)的異步編程萝究,使其輕量又高效。
例如锉罐,我們可以一邊讀取文件帆竹,一邊執(zhí)行其他命令,在文件讀取完成后氓鄙,我們將文件內(nèi)容作為回調(diào)函數(shù)的參數(shù)返回馆揉。這樣在執(zhí)行代碼時(shí)就沒(méi)有阻塞或等待文件 I/O 操作。
這就大大提高了 Node.js 的性能抖拦,可以處理大量的并發(fā)請(qǐng)求升酣,因此舷暮,Node 主要用在開(kāi)發(fā) Web 應(yīng)用。
使用原生nodejs提供web服務(wù)
要在nodejs中提供web服務(wù)噩茄,我們需要引入 nodejs 的Http模塊:require('http'), 然后調(diào)用createServer方法下面,傳入一個(gè)函數(shù)作為參數(shù)即可:
const Server = http.createServer((req, res) => {
res.writeHead(200,{'Content-Type': 'application/json;charset=utf-8;'});
res.write('{text: "寫(xiě)代碼很快樂(lè)啊!"}');
res.end();
}).listen(8888);
可以看到绩聘,代碼可讀性不是很好沥割,開(kāi)發(fā)也不是很便利,于是就有了 Express 這個(gè)第一代最流行的web框架凿菩。
express 框架
我們看看机杜,使用express, 怎么實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的入門(mén)網(wǎng)站:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('寫(xiě)代碼很快樂(lè)!');
});
app.listen(8888);
可以看到衅谷,代碼精簡(jiǎn)了很多椒拗,雖然express的API很簡(jiǎn)單,但是它是基于ES5的語(yǔ)法获黔,要實(shí)現(xiàn)異步代碼蚀苛,只有一個(gè)方法:回調(diào)。如果異步嵌套層次過(guò)多玷氏,代碼寫(xiě)起來(lái)就非常難看堵未,比如讀取一個(gè)文件成功后再讀取一個(gè)文件:
app.get('/file', function (req, res) {
fs.readFile('/file1', function (err, data) {
if (err) { res.status(500).send('讀取文件1失敗'); }
fs.readFile('/file2', function (err, data) {
if (err) { res.status(500).send('讀取文件2失敗'); }
res.type('text/plain');
res.send(data);
});
});
});
雖然可以用async這樣的庫(kù)來(lái)組織異步代碼,但是用回調(diào)寫(xiě)異步實(shí)在是太痛苦了盏触,特別是異步嵌套多的時(shí)候渗蟹,這就是JS遠(yuǎn)古時(shí)期的 回調(diào)地獄!
koa 1.x的到來(lái)
隨著ES6在新版Node.js獲得支持ES6赞辩,express的團(tuán)隊(duì)基于ES6的generator推出了koa這個(gè) web 框架拙徽。和express相比,koa 1.0使用generator實(shí)現(xiàn)異步诗宣,比如實(shí)現(xiàn)上面同樣的功能,代碼如下:
var koa = require('koa');
var app = koa();
app.use('/file', function *() {
yield readFile1();
var data = yield readFile2();
this.body = data;
});
app.listen(8888);
可以看到想诅,用generator實(shí)現(xiàn)異步比回調(diào)簡(jiǎn)單了不少召庞,但是generator的本意并不是異步。Promise才是為異步設(shè)計(jì)的来破,但是Promise的寫(xiě)法很復(fù)雜篮灼。為了簡(jiǎn)化異步代碼,ES7引入了新的關(guān)鍵字async和await徘禁,可以輕松地把一個(gè)function變?yōu)楫惒侥J剑?/p>
async function () {
var data = await fs.read('/file1');
}
最新的koa 2.x的到來(lái)
koa團(tuán)隊(duì)并沒(méi)有止步于koa 1.0诅诱,他們非常超前地基于ES7開(kāi)發(fā)了koa2,和koa 1相比送朱,koa2完全使用Promise并配合async來(lái)實(shí)現(xiàn)異步娘荡。
app.use(async (ctx, next) => {
await next();
var data = await readFile();
ctx.response.type = 'text/plain';
ctx.response.body = data;
});
通過(guò)以上分享干旁,大家可以看到,我們項(xiàng)目使用koa2炮沐,是按照node->express->koa1-<koa2 一步步隨著新的JS規(guī)范通過(guò)并獲得支持的發(fā)展而來(lái)的争群,出現(xiàn)的主要原因就是為了在node開(kāi)發(fā)中優(yōu)雅的寫(xiě)異步代碼。
express, koa1和koa2的區(qū)別
koa vs express
-
相同點(diǎn)
- 構(gòu)建 web 應(yīng)用的 node 框架
- 總體來(lái)看語(yǔ)法差別不大大年,比如都是引入后框架后實(shí)例后换薄,中間件處理以及監(jiān)聽(tīng)端口;
- 都是同一個(gè)團(tuán)隊(duì)開(kāi)發(fā)維護(hù)的
-
區(qū)別
- express: 框架內(nèi)容更豐富翔试,有更大的社區(qū)轻要,歷史更悠久,文檔更豐富垦缅,用戶(hù)群更大冲泥,支持 jade 等前端模板語(yǔ)言,express沒(méi)有統(tǒng)一的錯(cuò)誤處理失都,而koa有默認(rèn)的錯(cuò)誤處理方式柏蘑。
- koa: 更小、更富有表現(xiàn)力粹庞、更健壯咳焚,Koa 支持 es6 語(yǔ)法,Koa 在內(nèi)核方法中不綁定任何中間件庞溜,不提供路由功能和某些工具革半,摒棄了的回調(diào),采用 generator 或 promise的方式流码,在 Context中又官,Koa 對(duì) request 和 response 進(jìn)行了封裝,使用方式也相應(yīng)改變漫试,如返回簡(jiǎn)單內(nèi)容六敬,在koa: this.body = ‘hello world’,而在express: res.send(‘hello world’)驾荣。
koa1 vs koa2
- 中間件的使用: koa1依賴(lài) co 并采用 generator 函數(shù)外构,在函數(shù)內(nèi)使用 yield 語(yǔ)句,而koa2增加了箭頭函數(shù)播掷,移除了 co 依賴(lài)审编,使用 Promise,因此可以結(jié)合 async歧匈,await 使用垒酬;
- context 對(duì)象的獲取:koa1為this 對(duì)象,this.req, this.res勘究;koa2: cxt 參數(shù)矮湘,cxt.req, cxt.res。
了解了koa的背景知識(shí)后乱顾,下一節(jié)我們將簡(jiǎn)單分析其源碼啦板祝!