Koa

參考資料

Koa

環(huán)境部署

下載安裝NodeJS

下載地址: http://nodejs.cn/download/

$ node -v
v10.15.0

$ npm -v
6.4.1

Koa2

官網(wǎng):https://koa.bootcss.com/

Koa是基于Node.js平臺的下一臺Web開發(fā)框架看成,Koa是一個全新的Web框架嫌拣,由Express原班人馬打造,致力于成為Web應(yīng)用和API開發(fā)領(lǐng)域中更小且更加富有表現(xiàn)力蝗拿、更健壯的基石掷酗。通過async函數(shù)Koa幫你丟棄回調(diào)函數(shù),并有力地增強錯誤處理。Koa并沒有綁定任何中間件漓穿,而是提供了一套優(yōu)雅的方法幫助快速編寫服務(wù)器端應(yīng)用程序。

Koa2相比較Koa1最大區(qū)別在于中間件的寫法注盈,Koa1使用Generator晃危,Koa2使用async/await語法,因此Node.js必須大于v7.6.0+老客。

安裝

Koa依賴Node v7.6.0 或ES2015+ 和 async方法支持僚饭。

創(chuàng)建工程文件夾并進入,使用npm初始化項目胧砰。

# 手工創(chuàng)建項目
$ mkdir project && cd  project

# 快速生成package.json文件
$ npm init -y

$ vim package.json
{
  "name": "project",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"node app.js" // 添加快捷啟動命令
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
  }
}

運行腳本

可直接使用node app.js運行腳本鳍鸵,也可以使用它的快捷方式npm start運行app.js腳本。

$ node app.js
$ npm start

安裝Koa

$ npm install koa -S
$ npm i koa

應(yīng)用程序

Koa應(yīng)用程序是一個包含一組中間件函數(shù)的對象尉间,它按照類似堆棧的方式組織和執(zhí)行偿乖。Koa類似中間件系統(tǒng)。

$ vim app.js

導(dǎo)入Koa哲嘲,在Koa2中由于導(dǎo)入的是一個類贪薪,所以使用大寫的Koa。

const Koa = require("koa");

創(chuàng)建Koa對象眠副,即Web應(yīng)用本身app画切。

const app = new Koa();

對于任何HTTP請求,app將調(diào)用異步函數(shù)進行處理囱怕。

app.use(async (ctx, next)=>{
  await next();
  // 設(shè)置HTTP響應(yīng)的內(nèi)容類型
  ctx.response.type = "text/html";
  // 設(shè)置HTTP響應(yīng)的內(nèi)容
  ctx.response.body = "hello world";
});

每當(dāng)Koa收到一個HTTP請求時霍弹,會調(diào)用通過app.use()注冊的async異步函數(shù)并傳入ctxnext參數(shù)」馔浚可以針對ctx進行操作并設(shè)置返回內(nèi)容庞萍。

async標(biāo)記的函數(shù)稱為異步函數(shù),使用await調(diào)用另一個異步函數(shù)忘闻,async/await關(guān)鍵字是在ES7中引入的钝计。

ctx是Koa提供的Context對象,封裝了requestresponse對象,每次HTTP Request都會創(chuàng)建一個Context上下文對象私恬。

ctx是由Koa傳入的封裝了requestresponse的變量债沮,可通過ctx.requestctx.response訪問請求和響應(yīng)。

中間件

next是Koa傳入將要處理的下一個異步函數(shù)本鸣,await next();表示處理下一個異步函數(shù)疫衩,然后再設(shè)置response響應(yīng)的Content-Typebody內(nèi)容。

await next();有什么作用呢荣德?

Koa將多個async異步函數(shù)組成了一個處理鏈闷煤,每個async異步函數(shù)都可以做自己的事情,然后使用await next()來調(diào)用下一個async異步函數(shù)涮瞻。這里將每個async異步函數(shù)成為中間件middleware鲤拿,這些中間件可以組合起來完成很多實用的功能。

監(jiān)聽3000端口

app.listen(3000);

瀏覽器訪問:http://127.0.0.1:3000

JS異步發(fā)展史

  • ES5:回調(diào)函數(shù)callback
  • ES6:Promise對象和Generator函數(shù)
  • ES7:async/await語法

async/await

async用于聲明一個函數(shù)是異步的署咽,await只能出現(xiàn)在async修改的函數(shù)中近顷。async函數(shù)會返回一個promise對象,如果在async函數(shù)返回一個直接量它最終將通過Promise.resolve封裝成promise對象宁否,進而可以直接通過promise對象的then方法來獲取這個直接量窒升。

await會暫停當(dāng)前async的執(zhí)行,await會阻塞代碼的執(zhí)行直到await后的表達式處理完畢慕匠,代碼才繼續(xù)往下執(zhí)行饱须。await后的表達式可以是一個promise對象也可以任何需要等待的值。如果await等到的是一個promise對象絮重,await就會阻塞后續(xù)代碼直到promise對象resolve后得到resolve的值作為await表達式的運算結(jié)果冤寿。

async/await只是一種語法糖歹苦,其代碼執(zhí)行與回調(diào)函數(shù)嵌套是本質(zhì)上是沒有區(qū)別的青伤,只是寫法上讓人以同步的思維去思考,避開回調(diào)地獄殴瘦。簡而言之狠角,async/await是以同步的思維去編寫異步的代碼,所以async/await并不會影響Node.js的并發(fā)數(shù)蚪腋。

中間件

中間件類似于過濾器丰歌,用于在客戶端和應(yīng)用程序之間處理請求和響應(yīng)的方法。中間件的執(zhí)行類似剝洋蔥屉凯,但并非一層層的執(zhí)行立帖,而是以next為分界,先執(zhí)行本層next之前的部分悠砚,當(dāng)下一層中間件執(zhí)行完畢后再執(zhí)行本層next之后的部分晓勇。

中間件

中間件是為了解決復(fù)雜應(yīng)用中頻繁回調(diào)而設(shè)計的級聯(lián)式代碼,它并不直接將控制權(quán)完全交給下一個中間件,而是碰到next后去下一個中間件绑咱,等到下面都執(zhí)行完畢后在執(zhí)行next后續(xù)代碼绰筛。

例如:使用三個中間件組成處理鏈,依次打印日志描融,記錄處理時間铝噩,輸出HTML。

//中間件處理鏈
app.use(async (ctx, next) => {
    console.log(`${ctx.request.method} ${ctx.request.url}`);
    await next();//調(diào)用下一個中間件
});
app.use(async (ctx, next) => {
    const begin_time = new Date().getTime();
    await next();//處理下一個中間件
    const spend_ms = new Date().getTime() - begin_time;//耗費時間
    console.log(`Time: ${spend_ms}ms`);
});
app.use(async (ctx, next) => {
    await next();
    ctx.response.type = "text/html";
    ctx.response.body = "request received";
});

注意中間件的順序也就是調(diào)用app.use()的順序?qū)Q定了中間件的執(zhí)行順序窿克。如果某個中間件沒有調(diào)用await next()則后續(xù)中間件將不再執(zhí)行骏庸。

例如:檢測用戶權(quán)限的中間件可以決定是否繼續(xù)處理請求,若不則直接返回403錯誤年叮。

app.use(async (ctx, next) => {
    if(await checkAuth(ctx)){
        await next();
    }else{
        ctx.response.status = 403;
    }
});

簡單來說敞恋,理解了中間件也就學(xué)會使用Koa了。

獲取GET請求數(shù)據(jù)

Koa2中GET請求可通過ctx.request接收谋右,接收方式分為兩種:

  • ctx.request.query 獲取格式化后的參數(shù)對象
  • ctx.request.querystring 獲取請求字符串
  • ctx.query
  • ctx.querystring

例如:

app.use(async (ctx, next) => {
    const url = ctx.url;
    //使用ctx.request接收
    const rq = ctx.request;
    const rq_query = rq.query;
    const rq_qs = rq.querystring;
    //使用ctx接收
    const ctx_query = ctx.query;
    const ctx_qs = ctx.querystring;

    //返回
    body = {};
    body.rq_query = rq_query;
    body.rq_qs = rq_qs;
    body.ctx_query = ctx_query;
    body.ctx_qs = ctx_qs;
    ctx.body = body;
});

獲取POST請求數(shù)據(jù)

Koa2中沒有對POST請求的處理封裝獲取參數(shù)的方法硬猫,需要通過解析上下文ctx中的元素來獲取,具體可分為三步:

  1. 解析上下文ctx對象中的原生Node.js對象req
  2. 將POST表單數(shù)據(jù)解析為querystring查詢字符串
  3. 將查詢字符串轉(zhuǎn)換為JSON格式
const Koa = require("koa");
const app = new Koa();

const parseQueryString = (querystring) => {
    const queryData = {};
    const qsList = querystring.split("&");
    for(let [index, qs] of qsList.entries()){
        let kvList = qs.split("=");
        queryData[kvList[0]] = decodeURIComponent(kvList[1]);
    }
    return queryData;
};

const parsePostData = (ctx) => {
    return new Promise((resolve, reject) => {
        try{
            let postData = "";
            ctx.req.on("data", (data)=>{
                postData += data;
            })
            ctx.req.addListener("end", ()=>{
                let parseData = parseQueryString(postData);
                resolve(parseData);
            });
        }catch(error){
            reject(error);
        }
    });
};

app.use(async(ctx, next) => {
    if(ctx.method === "POST"){
        let postData = await parsePostData(ctx);
        ctx.body = postData;
    }
});

app.listen(3000, ()=>{
    console.log("server is running");
});

另一種方式是使用koa-bodyparser中間件改执,對于POST請求的處理啸蜜,koa-bodyparser中間件可以將Koa上下文中的formData數(shù)據(jù)解析到ctx.request.body中。

koa-bodyparser

安裝

$ npm i koa-bodyparser -S

使用

const Koa = require("koa");
const app = new Koa();

const bodyParser = require("koa-bodyparser");
app.use(bodyParser());

app.use(async(ctx, next) => {
    if(ctx.method === "POST"){
        ctx.body = ctx.request.body;
    }
});

app.listen(3000, ()=>{
    console.log("server is running");
});

supervisor

使用supervisor自動重啟模塊

$ npm i supervisor -g
# 修改package.json辈挂,設(shè)置scripts選項下的start衬横。
"scripts":
{
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"supervisor app.js" //設(shè)置npm start啟動項
}

koa-router

koa-router 路由組件

$ npm i koa-router -S
var Koa = require("koa");
var app = new Koa();
var router = require("koa-router")();

router.get("/", (ctx, next) => {
  console.log("homepage");
});

app.use(router.routes()).use(router.allowedMethods());

參考資料

koa-router是Koa的路由組件,路由的功能是指定具體的訪問路徑终蒂,通過訪問路徑指向特定的功能模塊蜂林。

安裝

# 安裝Koa
$ npm install koa --save

# 安裝koa-router
$ npm install koa-router --save

使用

var Koa = require("koa");
var Router = require("koa-router");

var app = new Koa();
var router = new Router();

app.use(router.routes()).use(router.allowedMethods());

router.get("/", (ctx, next)=>{

});

koa-simple-router

路由koa-simple-router

$ npm i koa-simple-router -S

koa-cors 跨域組件

安裝

$ npm install --save koa2-cors

使用

var Koa = require('koa');
var cors = require('koa2-cors');

var app = new Koa();
app.use(cors());

koa-static

koa-static為原生koa2實現(xiàn)靜態(tài)資源服務(wù)器

一個HTTP請求訪問Web服務(wù)靜態(tài)資源,一般響應(yīng)結(jié)果有3種情況:

  • 訪問文本拇泣,如css噪叙、js、image...
  • 訪問靜態(tài)目錄
  • 找不到資源則拋出404錯誤

為Koa2實現(xiàn)靜態(tài)資源加載的服務(wù)霉翔,用于訪問css/js/img等靜態(tài)資源睁蕾,若訪問圖片則返回二進制,其他文件則直接輸出字符串债朵。

$ npm i koa-static -S
# 設(shè)置static目錄用于存儲靜態(tài)資源子眶,app.js添加中間件。
app.use(require("koa-static")(__dirname + "/static"));

koa-views

koa-views為Koa2加載的模板引擎

$  npm i koa-views -S

根目錄下創(chuàng)建views目錄用于存儲視圖模板文件序芦,并在app.js文件中添加中間件配置臭杰。

//模板引擎
app.use(require("koa-views")(__dirname+"/views"));

koa-logger

//日志配置
app.use(require("koa-logger")());

koa-bodyparser

$ npm i koa-bodyparser@2 -S
app.use(require("koa-bodyparser")())

koa-session

$ npm i koa-session -S

mongoose

https://mongoosejs.com

$ npm i mongoose -S

config


$ npm i config -S

mysql

mysql模塊是node操作MySQL的引擎,可在node.js環(huán)境下對MySQL數(shù)據(jù)庫進行CURD等操作谚中。

$ npm i mysql -S
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渴杆,一起剝皮案震驚了整個濱河市射窒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌将塑,老刑警劉巖脉顿,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異点寥,居然都是意外死亡艾疟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門敢辩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔽莱,“玉大人,你說我怎么就攤上這事戚长〉晾洌” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵同廉,是天一觀的道長仪糖。 經(jīng)常有香客問我,道長迫肖,這世上最難降的妖魔是什么锅劝? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蟆湖,結(jié)果婚禮上故爵,老公的妹妹穿的比我還像新娘。我一直安慰自己隅津,他們只是感情好诬垂,可當(dāng)我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伦仍,像睡著了一般结窘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呢铆,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天晦鞋,我揣著相機與錄音,去河邊找鬼棺克。 笑死,一個胖子當(dāng)著我的面吹牛线定,可吹牛的內(nèi)容都是我干的娜谊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼斤讥,長吁一口氣:“原來是場噩夢啊……” “哼纱皆!你這毒婦竟也來了湾趾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤派草,失蹤者是張志新(化名)和其女友劉穎搀缠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體近迁,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡艺普,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鉴竭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歧譬。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖搏存,靈堂內(nèi)的尸體忽然破棺而出瑰步,到底是詐尸還是另有隱情,我是刑警寧澤璧眠,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布缩焦,位于F島的核電站,受9級特大地震影響责静,放射性物質(zhì)發(fā)生泄漏舌界。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一泰演、第九天 我趴在偏房一處隱蔽的房頂上張望呻拌。 院中可真熱鬧,春花似錦睦焕、人聲如沸藐握。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猾普。三九已至,卻和暖如春本谜,著一層夾襖步出監(jiān)牢的瞬間初家,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工乌助, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溜在,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓他托,卻偏偏與公主長得像掖肋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赏参,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,925評論 2 344

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

  • 目錄 一志笼、創(chuàng)建項目 二沿盅、配置路由 三、靜態(tài)資源 四纫溃、模板引擎 五腰涧、結(jié)語 Koa 是由 Express 原班人馬打造...
    880d91446f17閱讀 1,203評論 0 1
  • 內(nèi)容摘要 Node.js 10已經(jīng)進入LTS時代!其應(yīng)用場景已經(jīng)從腳手架紊浩、輔助前端開發(fā)(如SSR窖铡、PWA等)擴展到...
    iKcamp閱讀 1,954評論 0 1
  • 使用Koa搭建 基礎(chǔ)項目 一、創(chuàng)建項目 手動創(chuàng)建一個項目目錄郎楼,然后快速生成一個 package.json 文件np...
    隨風(fēng)飛2019閱讀 1,365評論 0 6
  • 隨著ES6的普及万伤,async/await的語法受到更多JS開發(fā)者的青睞,Koa.js作為比較早支持使用該語法的No...
    littleyu閱讀 1,404評論 0 20
  • 范仲淹《岳陽樓記》里這樣寫道:“不以物喜呜袁,不以己悲敌买。” 它所表達的是不因一時的成功而興高采烈阶界,也不要因為遭遇不順而...
    阿丹dan閱讀 504評論 0 0