Node 主要用在開發 Web 應用。這決定了使用 Node,每每離不開 Web 應用框架。前端
Koa 就是一種簡單好用的 Web 框架。它的特色是優雅、簡潔、表達力強、自由度高。自己代碼只有1000多行,全部功能都經過插件實現,很符合 Unix 哲學。java
本文從零開始,按部就班,教會你如何使用 Koa 寫出本身的 Web 應用。每一步都有簡潔易懂的示例,但願讓你們一看就懂。node
零、準備
首先,檢查 Node 版本。git
$ node -v v8.0.0
Koa 必須使用 7.6 以上的版本。若是你的版本低於這個要求,就要先升級 Node。es6
而後,克隆本文的配套示例庫。(若是不方便使用 Git,也能夠下載 zip 文件解壓。)github
$ git clone https://github.com/ruanyf/koa-demos.git
接着,進入示例庫,安裝依賴。web
$ cd koa-demos $ npm install
全部示例源碼,都在 demos 目錄下面。算法
1、基本用法
1.1 架設 HTTP 服務
只要三行代碼,就能夠用 Koa 架設一個 HTTP 服務。
// demos/01.js const Koa = require('koa'); const app = new Koa(); app.listen(3000);
運行這個腳本。
$ node demos/01.js
打開瀏覽器,訪問 http://127.0.0.1:3000 。你會看到頁面顯示"Not Found",表示沒有發現任何內容。這是由於咱們並無告訴 Koa 應該顯示什麼內容。
1.2 Context 對象
Koa 提供一個 Context 對象,表示一次對話的上下文(包括 HTTP 請求和 HTTP 回覆)。經過加工這個對象,就能夠控制返回給用戶的內容。
Context.response.body
屬性就是發送給用戶的內容。請看下面的例子(完整的代碼看這裏)。
// demos/02.js const Koa = require('koa'); const app = new Koa(); const main = ctx => { ctx.response.body = 'Hello World'; }; app.use(main); app.listen(3000);
上面代碼中,main
函數用來設置ctx.response.body
。而後,使用app.use
方法加載main
函數。
你可能已經猜到了,ctx.response
表明 HTTP Response。一樣地,ctx.request
表明 HTTP Request。
運行這個 demo。
$ node demos/02.js
訪問 http://127.0.0.1:3000 ,如今就能夠看到"Hello World"了。
1.3 HTTP Response 的類型
Koa 默認的返回類型是text/plain
,若是想返回其餘類型的內容,能夠先用ctx.request.accepts
判斷一下,客戶端但願接受什麼數據(根據 HTTP Request 的Accept
字段),而後使用ctx.response.type
指定返回類型。請看下面的例子(完整代碼看這裏)。
// demos/03.js const main = ctx => { if (ctx.request.accepts('xml')) { ctx.response.type = 'xml'; ctx.response.body = '<data>Hello World</data>'; } else if (ctx.request.accepts('json')) { ctx.response.type = 'json'; ctx.response.body = { data: 'Hello World' }; } else if (ctx.request.accepts('html')) { ctx.response.type = 'html'; ctx.response.body = '<p>Hello World</p>'; } else { ctx.response.type = 'text'; ctx.response.body = 'Hello World'; } };
運行這個 demo。
$ node demos/03.js
訪問 http://127.0.0.1:3000 ,如今看到的就是一個 XML 文檔了。
1.4 網頁模板
實際開發中,返回給用戶的網頁每每都寫成模板文件。咱們可讓 Koa 先讀取模板文件,而後將這個模板返回給用戶。請看下面的例子(完整代碼看這裏)。
// demos/04.js const fs = require('fs'); const main = ctx => { ctx.response.type = 'html'; ctx.response.body = fs.createReadStream('./demos/template.html'); };
運行這個 Demo。
$ node demos/04.js
訪問 http://127.0.0.1:3000 ,看到的就是模板文件的內容了。
2、路由
2.1 原生路由
網站通常都有多個頁面。經過ctx.request.path
能夠獲取用戶請求的路徑,由此實現簡單的路由。請看下面的例子(完整代碼看這裏)。
// demos/05.js const main = ctx => { if (ctx.request.path !== '/') { ctx.response.type = 'html'; ctx.response.body = '<a href="/">Index Page</a>'; } else { ctx.response.body = 'Hello World'; } };
運行這個 demo。
$ node demos/05.js
訪問 http://127.0.0.1:3000/about ,能夠看到一個連接,點擊後就跳到首頁。
2.2 koa-route 模塊
原生路由用起來不太方便,咱們可使用封裝好的koa-route
模塊。請看下面的例子(完整代碼看這裏)。
// demos/06.js const route = require('koa-route'); const about = ctx => { ctx.response.type = 'html'; ctx.response.body = '<a href="/">Index Page</a>'; }; const main = ctx => { ctx.response.body = 'Hello World'; }; app.use(route.get('/', main)); app.use(route.get('/about', about));
上面代碼中,根路徑/
的處理函數是main
,/about
路徑的處理函數是about
。
運行這個 demo。
$ node demos/06.js
訪問 http://127.0.0.1:3000/about ,效果與上一個例子徹底相同。
2.3 靜態資源
若是網站提供靜態資源(圖片、字體、樣式表、腳本......),爲它們一個個寫路由就很麻煩,也不必。koa-static
模塊封裝了這部分的請求。請看下面的例子(完整代碼看這裏)。
// demos/12.js const path = require('path'); const serve = require('koa-static'); const main = serve(path.join(__dirname)); app.use(main);
運行這個 Demo。
$ node demos/12.js
訪問 http://127.0.0.1:3000/12.js,在瀏覽器裏就能夠看到這個腳本的內容。
2.4 重定向
有些場合,服務器須要重定向(redirect)訪問請求。好比,用戶登錄之後,將他重定向到登錄前的頁面。ctx.response.redirect()
方法能夠發出一個302跳轉,將用戶導向另外一個路由。請看下面的例子(完整代碼看這裏)。
// demos/13.js const redirect = ctx => { ctx.response.redirect('/'); ctx.response.body = '<a href="/">Index Page</a>'; }; app.use(route.get('/redirect', redirect));
運行這個 demo。
$ node demos/13.js
訪問 http://127.0.0.1:3000/redirect ,瀏覽器會將用戶導向根路由。
3、中間件
3.1 Logger 功能
Koa 的最大特點,也是最重要的一個設計,就是中間件(middleware)。爲了理解中間件,咱們先看一下 Logger (打印日誌)功能的實現。
最簡單的寫法就是在main
函數裏面增長一行(完整代碼看這裏)。
// demos/07.js const main = ctx => { console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`); ctx.response.body = 'Hello World'; };
運行這個 Demo。
$ node demos/07.js
訪問 http://127.0.0.1:3000 ,命令行就會輸出日誌。
1502144902843 GET /
3.2 中間件的概念
上一個例子裏面的 Logger 功能,能夠拆分紅一個獨立函數(完整代碼看這裏)。
// demos/08.js const logger = (ctx, next) => { console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`); next(); } app.use(logger);
像上面代碼中的logger
函數就叫作"中間件"(middleware),由於它處在 HTTP Request 和 HTTP Response 中間,用來實現某種中間功能。app.use()
用來加載中間件。
基本上,Koa 全部的功能都是經過中間件實現的,前面例子裏面的main
也是中間件。每一箇中間件默認接受兩個參數,第一個參數是 Context 對象,第二個參數是next
函數。只要調用next
函數,就能夠把執行權轉交給下一個中間件。
運行這個 demo。
$ node demos/08.js
訪問 http://127.0.0.1:3000 ,命令行窗口會顯示與上一個例子相同的日誌輸出。
3.3 中間件棧
多箇中間件會造成一個棧結構(middle stack),以"先進後出"(first-in-last-out)的順序執行。
- 最外層的中間件首先執行。
- 調用
next
函數,把執行權交給下一個中間件。- ...
- 最內層的中間件最後執行。
- 執行結束後,把執行權交回上一層的中間件。
- ...
- 最外層的中間件收回執行權以後,執行
next
函數後面的代碼。
請看下面的例子(完整代碼看這裏)。
// demos/09.js const one = (ctx, next) => { console.log('>> one'); next(); console.log('<< one'); } const two = (ctx, next) => { console.log('>> two'); next(); console.log('<< two'); } const three = (ctx, next) => { console.log('>> three'); next(); console.log('<< three'); } app.use(one); app.use(two); app.use(three);
運行這個 demo。
$ node demos/09.js
訪問 http://127.0.0.1:3000 ,命令行窗口會有以下輸出。
>> one >> two >> three << three << two << one
若是中間件內部沒有調用next
函數,那麼執行權就不會傳遞下去。做爲練習,你能夠將two
函數裏面next()
這一行註釋掉再執行,看看會有什麼結果。
3.4 異步中間件
迄今爲止,全部例子的中間件都是同步的,不包含異步操做。若是有異步操做(好比讀取數據庫),中間件就必須寫成 async 函數。請看下面的例子(完整代碼看這裏)。
// demos/10.js const fs = require('fs.promised'); const Koa = require('koa'); const app = new Koa(); const main = async function (ctx, next) { ctx.response.type = 'html'; ctx.response.body = await fs.readFile('./demos/template.html', 'utf8'); }; app.use(main); app.listen(3000);
上面代碼中,fs.readFile
是一個異步操做,必須寫成await fs.readFile()
,而後中間件必須寫成 async 函數。
運行這個 demo。
$ node demos/10.js
訪問 http://127.0.0.1:3000 ,就能夠看到模板文件的內容。
3.5 中間件的合成
koa-compose
模塊能夠將多箇中間件合成爲一個。請看下面的例子(完整代碼看這裏)。
// demos/11.js const compose = require('koa-compose'); const logger = (ctx, next) => { console.log(`${Date.now()} ${ctx.request.method} ${ctx.request.url}`); next(); } const main = ctx => { ctx.response.body = 'Hello World'; }; const middlewares = compose([logger, main]); app.use(middlewares);
運行這個 demo。
$ node demos/11.js
訪問 http://127.0.0.1:3000 ,就能夠在命令行窗口看到日誌信息。
4、錯誤處理
4.1 500 錯誤
若是代碼運行過程當中發生錯誤,咱們須要把錯誤信息返回給用戶。HTTP 協定約定這時要返回500狀態碼。Koa 提供了ctx.throw()
方法,用來拋出錯誤,ctx.throw(500)
就是拋出500錯誤。請看下面的例子(完整代碼看這裏)。
// demos/14.js const main = ctx => { ctx.throw(500); };
運行這個 demo。
$ node demos/14.js
訪問 http://127.0.0.1:3000,你會看到一個500錯誤頁"Internal Server Error"。
4.2 404錯誤
若是將ctx.response.status
設置成404,就至關於ctx.throw(404)
,返回404錯誤。請看下面的例子(完整代碼看這裏)。
// demos/15.js const main = ctx => { ctx.response.status = 404; ctx.response.body = 'Page Not Found'; };
運行這個 demo。
$ node demos/15.js
訪問 http://127.0.0.1:3000 ,你就看到一個404頁面"Page Not Found"。
4.3 處理錯誤的中間件
爲了方便處理錯誤,最好使用try...catch
將其捕獲。可是,爲每一箇中間件都寫try...catch
太麻煩,咱們可讓最外層的中間件,負責全部中間件的錯誤處理。請看下面的例子(完整代碼看這裏)。
// demos/16.js const handler = async (ctx, next) => { try { await next(); } catch (err) { ctx.response.status = err.statusCode || err.status || 500; ctx.response.body = { message: err.message }; } }; const main = ctx => { ctx.throw(500); }; app.use(handler); app.use(main);
運行這個 demo。
$ node demos/16.js
訪問 http://127.0.0.1:3000 ,你會看到一個500頁,裏面有報錯提示 {"message":"Internal Server Error"}
。
4.4 error 事件的監聽
運行過程當中一旦出錯,Koa 會觸發一個error
事件。監聽這個事件,也能夠處理錯誤。請看下面的例子(完整代碼看這裏)。
// demos/17.js const main = ctx => { ctx.throw(500); }; app.on('error', (err, ctx) => console.error('server error', err); );
運行這個 demo。
$ node demos/17.js
訪問 http://127.0.0.1:3000 ,你會在命令行窗口看到"server error xxx"。
4.5 釋放 error 事件
須要注意的是,若是錯誤被try...catch
捕獲,就不會觸發error
事件。這時,必須調用ctx.app.emit()
,手動釋放error
事件,才能讓監聽函數生效。請看下面的例子(完整代碼看這裏)。
// demos/18.js` const handler = async (ctx, next) => { try { await next(); } catch (err) { ctx.response.status = err.statusCode || err.status || 500; ctx.response.type = 'html'; ctx.response.body = '<p>Something wrong, please contact administrator.</p>'; ctx.app.emit('error', err, ctx); } }; const main = ctx => { ctx.throw(500); }; app.on('error', function(err) { console.log('logging error ', err.message); console.log(err); });
上面代碼中,main
函數拋出錯誤,被handler
函數捕獲。catch
代碼塊裏面使用ctx.app.emit()
手動釋放error
事件,才能讓監聽函數監聽到。
運行這個 demo。
$ node demos/18.js
訪問 http://127.0.0.1:3000 ,你會在命令行窗口看到logging error
。
5、Web App 的功能
5.1 Cookies
ctx.cookies
用來讀寫 Cookie。請看下面的例子(完整代碼看這裏)。
// demos/19.js const main = function(ctx) { const n = Number(ctx.cookies.get('view') || 0) + 1; ctx.cookies.set('view', n); ctx.response.body = n + ' views'; }
運行這個 demo。
$ node demos/19.js
訪問 http://127.0.0.1:3000 ,你會看到1 views
。刷新一次頁面,就變成了2 views
。再刷新,每次都會計數增長1。
5.2 表單
Web 應用離不開處理表單。本質上,表單就是 POST 方法發送到服務器的鍵值對。koa-body
模塊能夠用來從 POST 請求的數據體裏面提取鍵值對。請看下面的例子(完整代碼看這裏)。
// demos/20.js const koaBody = require('koa-body'); const main = async function(ctx) { const body = ctx.request.body; if (!body.name) ctx.throw(400, '.name required'); ctx.body = { name: body.name }; }; app.use(koaBody());
運行這個 demo。
$ node demos/20.js
打開另外一個命令行窗口,運行下面的命令。
$ curl -X POST --data "name=Jack" 127.0.0.1:3000 {"name":"Jack"} $ curl -X POST --data "name" 127.0.0.1:3000 name required
上面代碼使用 POST 方法向服務器發送一個鍵值對,會被正確解析。若是發送的數據不正確,就會收到錯誤提示。
2.3 文件上傳
koa-body
模塊還能夠用來處理文件上傳。請看下面的例子(完整代碼看這裏)。
// demos/21.js const os = require('os'); const path = require('path'); const koaBody = require('koa-body'); const main = async function(ctx) { const tmpdir = os.tmpdir(); const filePaths = []; const files = ctx.request.body.files || {}; for (let key in files) { const file = files[key]; const filePath = path.join(tmpdir, file.name); const reader = fs.createReadStream(file.path); const writer = fs.createWriteStream(filePath); reader.pipe(writer); filePaths.push(filePath); } ctx.body = filePaths; }; app.use(koaBody({ multipart: true }));
運行這個 demo。
$ node demos/21.js
打開另外一個命令行窗口,運行下面的命令,上傳一個文件。注意,/path/to/file
要更換爲真實的文件路徑。
$ curl --form upload=@/path/to/file http://127.0.0.1:3000 ["/tmp/file"]
6、參考連接
(完)
龍捲 說:
正在用koa 教程這就來了!
2017年8月 9日 08:35 | # | 引用
韓帥 說:
簡單易用
2017年8月 9日 09:15 | # | 引用
業餘草 說:
講的很詳細!
Koa -- 基於 Node.js 平臺的下一代 web 開發框架!
2017年8月 9日 09:22 | # | 引用
陳愷垣 說:
感謝,以前一直在用express
2017年8月 9日 09:36 | # | 引用
理斯特 說:
阮老師爲啥不直接介紹 egg.js
2017年8月 9日 09:40 | # | 引用
disguiser 說:
不是很理解爲何要把多箇中間件合成爲一個
2017年8月 9日 10:26 | # | 引用
MarshallStan 說:
感謝阮一峯老師。
2017年8月 9日 10:33 | # | 引用
wuyang 說:
講的很詳細 贊
2017年8月 9日 12:32 | # | 引用
shadow 說:
感謝分享~前幾天恰好在入門Koa2
2017年8月 9日 13:38 | # | 引用
csjiabin 說:
koa和express哪一個比較好 我如今一直在用express 據說koa小 想試試
2017年8月 9日 13:50 | # | 引用
郭 說:
不太理解爲什麼要作中間件的合成(koa-compose),阮一峯老師,不知這有什麼應用的場景?既然都是中間件,都是按順序執行,爲什麼還有作合成?是方便多箇中間件,有公用的部分,可屢次應用在不一樣中間件上?
2017年8月 9日 15:42 | # | 引用
詩與遠方 說:
正在學習koa2!
2017年8月 9日 15:59 | # | 引用
magicbing 說:
感受koa和express都是簡潔的小框架。
像ror或者django那種大框架好像有sails和adonis,不過感受也不是很成熟
2017年8月 9日 16:32 | # | 引用
CODE大全 說:
阮老師的文章都是圖文並茂,並且demo和源碼都很詳細!koa框架正在學習中!
2017年8月 9日 16:54 | # | 引用
cshenger 說:
阮老師的入門系列一貫簡介明瞭
2017年8月 9日 17:49 | # | 引用
cdd 說:
我記得koa文檔中koa.request/koa.response是其自身封裝的對象吧。koa.req/koa.res是node的對象。
2017年8月 9日 19:38 | # | 引用
李家梁 說:
我用koa2幾個月了,
路由用的最多的是koa-router,
文件上傳能夠試試koa-multer
2017年8月 9日 19:43 | # | 引用
久伴我暖 說:
膜拜一下前端界的大佬。分享了最新又是值得學習的框架,學習前留個言。
2017年8月 9日 22:05 | # | 引用
MorningTZH 說:
哈哈哈 我也是,瞌睡送枕頭呢。
2017年8月 9日 22:40 | # | 引用
宇宙全棧 說:
是時候從 express 換到 koa 了!
2017年8月10日 11:41 | # | 引用
Naomi 說:
node 檢查出來是6的版本,可是用brew更新的是8的版本,會有影響嗎
2017年8月10日 12:22 | # | 引用
MurakamiKennzo 說:
受益不淺
2017年8月10日 15:55 | # | 引用
阮榮軍 說:
passport 官網 http://www.passportjs.org/
2017年8月10日 16:10 | # | 引用
安晗 說:
很是想提高一下自身做爲web前端的能力和素質,看了一些帖子,都推薦來看一下阮老師的教程,之後我會多多關注您,把您的教程都好好學習,祝阮老師身體健康,爲咱們寫出更多的精品教程。
2017年8月10日 16:36 | # | 引用
feilong 說:
Error: Cannot find module 'koa' = =,老師怎麼回事?
2017年8月10日 17:44 | # | 引用
桂梅桑 說:
清晰明瞭~
2017年8月10日 21:56 | # | 引用
coldxu 說:
阮老師寫的太全了,幾乎初學全部點都涵蓋到了,感謝。
2017年8月10日 22:43 | # | 引用
Phlip 說:
阮老師,求分享算法和互聯網架構的內容。
2017年8月11日 14:33 | # | 引用
劉煜 說:
你沒有安裝依賴,在node demos/01.js以前,你須要命令行執行npm install
2017年8月14日 15:05 | # | 引用
distance 說:
好小巧啊~~之前一點點地開始學node.js感受什麼都要本身考慮到,各類處理。後來看了express,使用起來方便多了,也很小巧~~如今又在這裏看了koa
2017年8月14日 15:05 | # | 引用
vista-hey 說:
阮老師 ··又是4個多月纔等的您的一次更新··可是值得
2017年8月14日 18:03 | # | 引用
wells 說:
官方文檔是這樣
2017年8月14日 20:06 | # | 引用
van 說:
3.5 中件 是中間件吧,少打了一個字。
2017年8月15日 16:57 | # | 引用
阮一峯 說:
@van:謝謝指出,已經改正了。
2017年8月15日 18:12 | # | 引用
kindhj 說:
數據庫邏輯處理呢。。?本人小白
2017年8月15日 19:55 | # | 引用
bianhognfei 說:
阮哥你好,你都用什麼工具寫博客的,我如今也想作一個本身的博客,來寫博客。
2017年8月21日 16:23 | # | 引用
ovnrain 說:
用Koa本身寫一個啊^_^
2017年8月23日 18:56 | # | 引用
謝東磊 說:
const handler = async (ctx, next) => {
^
SyntaxError: Unexpected token
好幾個例子報這樣的錯誤是怎麼回事
2017年8月25日 22:29 | # | 引用
~~~ 說:
@謝東磊:
不識別箭頭函數吧
2017年8月28日 17:51 | # | 引用
mdz 說:
爲何路由介紹使用的是koa-route沒有使用koa-router
2017年8月29日 13:08 | # | 引用
十三 說:
koa2 由於須要async await 的緣由須要node版本在7以上,koa1不須要
2017年9月 2日 18:09 | # | 引用
hdp 說:
2017年9月 8日 13:33 | # | 引用
linzx 說:
DeprecationWarning: Calling an asynchronous function wit
hout callback is deprecated.
3.4節使用async異步編程那裏報了這個錯,查了下,說這個API廢棄了,你們是怎麼解決的啊
2017年9月13日 22:53 | # | 引用
達文西12138 說:
有相似Express那種已經搭建好一點的koa框架模板嗎?一些404,路由等都配置好了的
2017年9月14日 16:21 | # | 引用
張志成 說:
是koa-router不是koa-route,少了個r
2017年9月23日 22:45 | # | 引用
張志成 說:
說錯了,這兩個插件都存在,koa-route貌似是官方的,可是koa-router的star多一點
2017年9月23日 23:29 | # | 引用
老黃 說:
sequelize
2017年9月25日 16:40 | # | 引用
海的女兒前端博客 說:
用koa架設http服務器的,來看下,之後可能會用到
2017年10月 9日 16:34 | # | 引用
microbingbing 說:
爲何是下一代?比express有什麼優點麼?
2017年10月11日 16:35 | # | 引用
小濤 說:
好像有個小的筆誤,應該是koa-router, 而不是koa-route
2017年10月14日 10:38 | # | 引用
頓頓 說:
06.js 這句是多餘的?
app.use(main);
2017年10月21日 00:23 | # | 引用
G小健 說:
比官網講得好。每次有什麼問題不懂,發現阮老師寫過日誌,就安心了
2017年10月25日 16:53 | # | 引用
hackjay 說:
確實看到你的文章比較多,謝謝你的分享,會繼續關注你的,但願出些實用的高級課程學學
2017年11月10日 18:08 | # | 引用
GS 說:
koa-route 和 koa-router 兩個太像了!阮一峯用的 koa-route, 廖雪峯用的 koa-router
2017年11月14日 14:34 | # | 引用
JQ_Chan 說:
我想請問下在異步中間件的demo中main前面還能夠增長其餘中間件麼?怎麼加了好像會報錯
2017年12月 8日 16:22 | # | 引用
stillyu 說:
5.2表單
ctx.body = ''
寫錯了
2017年12月21日 12:51 | # | 引用
王 說:
koa比express好不少,正在學習node,發現若是用express框架編寫程序是要私人的感受,各類回掉,仍是koa比較正常一點,受教了!
2017年12月27日 02:33 | # | 引用
青伢子 說:
兩個都是能夠的
2018年1月10日 23:45 | # | 引用
金牌紅豆 說:
太棒了!受益不淺!! 前端學習這個感受像打開了新世界的大門!!感謝阮老師
2018年1月19日 16:52 | # | 引用
姜珊 說:
Koa是默認127.0.0.1的主機名嗎?在哪裏能夠更改
2018年1月25日 20:24 | # | 引用
姜珊 說:
koa能夠處理PUT請求嗎?
2018年1月27日 10:03 | # | 引用
楊毅 說:
最後一節的用來上傳的那裏有點不明白,能夠展現一個跟html前臺頁面結合的上傳代碼嗎
2018年1月29日 15:05 | # | 引用
ranyingxia 說:
求出一個 koa 與 MongoDB 結合的 demo 教程
2018年2月 5日 18:11 | # | 引用
王澤 說:
老師您好,我想問下,demos/09.js的示例爲何我執行時觸發了兩次中間件?我看您的運行結果也只是觸發一次呀
2018年2月 8日 22:43 | # | 引用
k 說:
demos/05.js 與 demos/06.js 不徹底同樣。http://127.0.0.1:3000/aboux 的結果就不同。
2018年2月20日 13:03 | # | 引用
alisx 說:
5.2 的示例中,中間件main裏,並無 await 表示,爲何main函數須要聲明成 async?
2018年2月24日 11:56 | # | 引用
alisx 說:
我去掉了main的async聲明,結果一樣有效
2018年2月24日 12:01 | # | 引用
lp 說:
贊成!!!!!
求解
2018年2月26日 11:41 | # | 引用
很久不見 說:
用了很久的express框架,忽然須要作一個blog,是基於koa而且用render後端渲染,確實koa是大勢所趨
2018年2月26日 11:47 | # | 引用
Sumii 說:
懂了好多,哈哈謝謝!
2018年2月27日 15:19 | # | 引用
1Q84 說:
koa裏能夠用bootstrap嗎?目前沒找到較爲詳細的教程,使用中遇到不少問題
2018年3月 1日 12:52 | # | 引用
ben 說:
求解10.js運行報錯是什麼緣由呢 Unexpected token function
2018年3月20日 11:48 | # | 引用
楊毅 說:
使用koa-body上傳文件的時候,沒法獲取其餘表單的值,這個要怎麼辦?
2018年3月27日 09:56 | # | 引用
小邁克 說:
一年前還看不懂阮一峯老師的教程,如今感受簡單易懂。
2018年4月 7日 13:34 | # | 引用
嘿嘿 說:
常常看阮一峯老師的博客,受益不少
2018年4月 7日 17:12 | # | 引用
Casey 說:
$ curl -X POST --data "name=Jack" 127.0.0.1:3000
{"name":"Jack"}\
curl不是內部或外部命令,這個怎麼解決,在window7下
2018年4月10日 09:43 | # | 引用
靈谷 說:
今天發了一上午看完,教程簡潔明瞭!入門法寶!很是謝謝老師!在你這裏學到了不少東西!學會了不少!所謂「師傅引進門,修行看我的」,在前端這個行業,並無系統的專業教育(反正咱們學校沒有),全靠自學和培訓~-~。繼續奮鬥吧!
2018年4月13日 13:50 | # | 引用
wopelo 說:
@lp:
我感受是由於若是有多箇中間件須要使用,那麼就得寫多個app.use(),使用koa-compose的話直接把中間件寫到參數中,最後只須要寫一個app.use()便可
2018年4月16日 15:25 | # | 引用
alisx 說:
在5.2的代碼示例中第4行
------------------
1 // demos/20.js
2 const koaBody = require('koa-body');
3
4 const main = async function(ctx) {
5 const body = ctx.request.body;
6 if (!body.name) ctx.throw(400, '.name required');
7 ctx.body = { name: body.name };
8 };
-------------------
main 是個異步方法,但從代碼來看,沒有異步的過程,請問
1 是否沒有必要聲明 async
2 是否出於將來代碼變動考慮,將全部的方法都聲明爲 async,這樣是好仍是很差?會有性能或其餘問題嗎?
謝謝!
2018年4月24日 18:33 | # | 引用
每天 說:
同感!
2018年5月 9日 10:35 | # | 引用
scs 說:
看了後,有了初步的瞭解,比較簡潔。
2018年6月11日 09:37 | # | 引用
dearest 說:
node 必須用7.6以上的版本, 寫成了 「Koa 必須使用 7.6 以上的版本」
2018年6月21日 14:47 | # | 引用
青格勒 說:
我在項目中也開始使用koa了
2018年7月 8日 17:52 | # | 引用
yinsang 說:
5.1 Cookies裏面
因爲favicon.icon 的http會執行兩次,因此views前的數變成一、三、五、7。
須要用route規避一下
2018年7月12日 10:12 | # | 引用
IndraNyo 說:
重定向這裏
ctx.response.redirect('/');
ctx.response.body = 'Index Page';
第二行好像不執行 已經重定向走了 應該在 route.get('/', XXX)的route裏寫 纔會輸出吧
仍是我操做不對?請老師指教
2018年7月31日 14:35 | # | 引用
jackletter 說:
「3.4 異步中間件」部分,
await fs.readFile('./demos/template.html', 'utf8')
顯示報錯,改爲await fs.readFileSync('package.json','utf-8');就行了
2018年8月 8日 11:40 | # | 引用
Ed Me 說:
koa-router 好像更利於項目工程
2018年8月16日 15:37 | # | 引用
Jack Chen 說:
阮老師小弟是看你博客長大的
2018年9月 8日 14:24 | # | 引用
郭小帥 說:
我測試了一下,其實是有執行,可是執行以後被重定向的內容又覆蓋掉了。
2018年9月10日 18:08 | # | 引用
意外金喜 說:
fs.readFile是回調的方法吧,await後面須要返回 Promise ,回調會報錯。
2018年9月13日 14:18 | # | 引用
xiaohuangmao 說:
通俗易懂
2018年9月14日 10:07 | # | 引用
hooper 說:
畫蛇添足