Koa 應(yīng)用程序是一個(gè)包含一組中間件函數(shù)的對象,它是按照類似堆棧的方式組織和執(zhí)行的。 Koa 類似于你可能遇到過的許多其他中間件系統(tǒng),例如 Ruby 的 Rack ,Connect 等,然而,一個(gè)關(guān)鍵的設(shè)計(jì)點(diǎn)是在其低級中間件層中提供高級“語法糖”。 這提高了互操作性,穩(wěn)健性,并使書寫中間件更加愉快。
這包括諸如內(nèi)容協(xié)商,緩存清理,代理支持和重定向等常見任務(wù)的方法。 盡管提供了相當(dāng)多的有用的方法 Koa 仍保持了一個(gè)很小的體積,因?yàn)闆]有捆綁中間件。
必修的 hello world 應(yīng)用:
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
Koa 中間件以更傳統(tǒng)的方式級聯(lián),您可能習(xí)慣使用類似的工具 - 之前難以讓用戶友好地使用 node 的回調(diào)。然而,使用 async 功能,我們可以實(shí)現(xiàn) “真實(shí)” 的中間件。對比 Connect 的實(shí)現(xiàn),通過一系列功能直接傳遞控制,直到一個(gè)返回,Koa 調(diào)用“下游”,然后控制流回“上游”。
下面以 “Hello World” 的響應(yīng)作為示例,當(dāng)請求開始時(shí)首先請求流通過 x-response-time 和 logging 中間件,然后繼續(xù)移交控制給 response 中間件。當(dāng)一個(gè)中間件調(diào)用 next() 則該函數(shù)暫停并將控制傳遞給定義的下一個(gè)中間件。當(dāng)在下游沒有更多的中間件執(zhí)行后,堆棧將展開并且每個(gè)中間件恢復(fù)執(zhí)行其上游行為。
const Koa = require('koa');
const app = new Koa();
// logger
app.use(async (ctx, next) => {
await next();
const rt = ctx.response.get('X-Response-Time');
console.log(`${ctx.method} ${ctx.url} - ${rt}`);
});
// x-response-time
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// response
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000);
應(yīng)用程序設(shè)置是 app 實(shí)例上的屬性,目前支持如下:
您可以將設(shè)置傳遞給構(gòu)造函數(shù):
const Koa = require('koa');
const app = new Koa({ proxy: true });
或動態(tài)的:
const Koa = require('koa');
const app = new Koa();
app.proxy = true;
Koa 應(yīng)用程序不是 HTTP 服務(wù)器的1對1展現(xiàn)。 可以將一個(gè)或多個(gè) Koa 應(yīng)用程序安裝在一起以形成具有單個(gè)HTTP服務(wù)器的更大應(yīng)用程序。
創(chuàng)建并返回 HTTP 服務(wù)器,將給定的參數(shù)傳遞給 Server#listen()。這些內(nèi)容都記錄在 nodejs.org.
以下是一個(gè)無作用的 Koa 應(yīng)用程序被綁定到 3000 端口:
const Koa = require('koa');
const app = new Koa();
app.listen(3000);
這里的 app.listen(...) 方法只是以下方法的語法糖:
const http = require('http');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
這意味著您可以將同一個(gè)應(yīng)用程序同時(shí)作為 HTTP 和 HTTPS 或多個(gè)地址:
const http = require('http');
const https = require('https');
const Koa = require('koa');
const app = new Koa();
http.createServer(app.callback()).listen(3000);
https.createServer(app.callback()).listen(3001);
返回適用于 http.createServer() 方法的回調(diào)函數(shù)來處理請求。你也可以使用此回調(diào)函數(shù)將 koa 應(yīng)用程序掛載到 Connect/Express 應(yīng)用程序中。
將給定的中間件方法添加到此應(yīng)用程序。參閱 Middleware 獲取更多信息.
設(shè)置簽名的 Cookie 密鑰。
這些被傳遞給 KeyGrip,但是你也可以傳遞你自己的 KeyGrip 實(shí)例。
例如,以下是可以接受的:
app.keys = ['im a newer secret', 'i like turtle'];
app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
這些密鑰可以倒換,并在使用 { signed: true } 參數(shù)簽名 Cookie 時(shí)使用。
ctx.cookies.set('name', 'tobi', { signed: true });
app.context 是從其創(chuàng)建 ctx 的原型。您可以通過編輯 app.context 為 ctx 添加其他屬性。這對于將 ctx 添加到整個(gè)應(yīng)用程序中使用的屬性或方法非常有用,這可能會更加有效(不需要中間件)和/或 更簡單(更少的 require()),而更多地依賴于ctx,這可以被認(rèn)為是一種反模式。
例如,要從 ctx 添加對數(shù)據(jù)庫的引用:
app.context.db = db();
app.use(async ctx => {
console.log(ctx.db);
});
注意:
默認(rèn)情況下,將所有錯(cuò)誤輸出到 stderr,除非 app.silent 為 true。 當(dāng) err.status 是 404 或 err.expose 是 true 時(shí)默認(rèn)錯(cuò)誤處理程序也不會輸出錯(cuò)誤。 要執(zhí)行自定義錯(cuò)誤處理邏輯,如集中式日志記錄,您可以添加一個(gè) “error” 事件偵聽器:
app.on('error', err => {
log.error('server error', err)
});
如果 req/res 期間出現(xiàn)錯(cuò)誤,并且 _無法_ 響應(yīng)客戶端,Context實(shí)例仍然被傳遞:
app.on('error', (err, ctx) => {
log.error('server error', err, ctx)
});
當(dāng)發(fā)生錯(cuò)誤 _并且_ 仍然可以響應(yīng)客戶端時(shí),也沒有數(shù)據(jù)被寫入 socket 中,Koa 將用一個(gè) 500 “內(nèi)部服務(wù)器錯(cuò)誤” 進(jìn)行適當(dāng)?shù)捻憫?yīng)。在任一情況下,為了記錄目的,都會發(fā)出應(yīng)用級 “錯(cuò)誤”。
更多建議: