ゼロからType Script版Kooaを実現
32948 ワード
この文章は何が話せますか?どうやってゼロからコア機能をカバーするNode.jsクラス を完成しますか? KKAコードの書き方のいくつかの理由をコードレベルから説明します。なぜ中間部品がnext関数、ctxがどのようにして来たのかと要求は何の関係ですか?
Kooaクラスライブラリは主に以下のいくつかの重要な特性があることを知っています。 は、玉葱リングモデルのミドルウェア機構 をサポートする。カプセル化request、reponseはcontextオブジェクトを提供し、http操作が便利です。 非同期関数、ミドルウェアのエラー処理機構 第一歩:ベースServer運転
目標:基礎を完成して新しいKooa Serverを実行します。は、ap.listen傍受ポートをサポートし、Server を起動する。サポートap.use追加クラスmiddleware処理関数 コアコードは以下の通りです。
目標:これから私達はlistenとuseの方法を改善して、玉葱リングの中間部品のモデルを実現します。
[外部チェーン写真の転載失敗(img-qyztqNsK-158619865571)(.asets/koaumidedleare.png)]
以下のコードに示すように、このステップでは、複数の中間部品を追加することをサポートし、中間部品はタマネギ圏(同様の深さ再帰呼び出し)の方式で順次実行してほしい。ミドルウェア内のnext()関数は必須であり、一回だけ を呼び出すことができます。 next関数を呼び出すときはawait を使用しなければなりません。
私たちは次のコードの中でこれらの使い方の原因を一つ一つ分析します。具体的にどのようにこのオニオンリング機構を実現するかを見てみます。 async関数はPromiseオブジェクトを返します。 async関数内部でawait呼出時にawait関数の実行が一時停止されます。戻り結果を待って、下の を続けます。 async関数の内部にエラーが発生し、戻ってきたPromiseがreject状態 になります。
今私たちが振り返る前に提出したいくつかの問題: koaミドルウェアはなぜ必須で、一度だけnext関数 を呼び出すことができますか? next()なぜawaitを追加する必要がありますか?
第三ステップ:Contect提供
目標:パッケージングContect、request、reponseの便利な操作方式を提供する。
ターゲット:ap.on(「error」)によるエラーイベントの処理異常の監視
私達はKooの中でどのように異常を処理するかを思い出します。コードは以下のようになるかもしれません。 KKAインスタンスアプリは、イベントトリガ、イベント傍受能力をサポートする必要がある は、非同期関数異常の捕獲を必要とし、errorイベント をトリガする。
具体的なコードはどうやって実現されますか?
これまでType Scriptを使って、簡単版Kooaクラスライブラリを完成しました。サポートしました。オニオンリング中間部品機構 Contectパッケージrequest、reponse 非同期異常エラー処理機構 完全なDemoコードは、koa 2-referenceを参照することができます。
より多くの素晴らしい文章、皆様を歓迎します。私達は毎週いくつかの高品質の先端領域に関する文章を発表します。
参考資料 Kooa 2中間部品機構を深く理解する は、現在の最も完全なソースコード解析ガイドかもしれません。
Kooaクラスライブラリは主に以下のいくつかの重要な特性があることを知っています。
目標:基礎を完成して新しいKooa Serverを実行します。
class Koa {
private middleware: middlewareFn = () => {};
constructor() {}
listen(port: number, cb: noop) {
const server = http.createServer((req, res) => {
this.middleware(req, res);
});
return server.listen(port, cb);
}
use(middlewareFn: middlewareFn) {
this.middleware = middlewareFn;
return this;
}
}
const app = new Koa();
app.use((req, res) => {
res.writeHead(200);
res.end("A request come in");
});
app.listen(3000, () => {
console.log("Server listen on port 3000");
});
第二ステップ:オニオンリング中間部品機構の実現目標:これから私達はlistenとuseの方法を改善して、玉葱リングの中間部品のモデルを実現します。
[外部チェーン写真の転載失敗(img-qyztqNsK-158619865571)(.asets/koaumidedleare.png)]
以下のコードに示すように、このステップでは、複数の中間部品を追加することをサポートし、中間部品はタマネギ圏(同様の深さ再帰呼び出し)の方式で順次実行してほしい。
app.use(async (req, res, next) => {
console.log("middleware 1 start");
//
await next();
console.log("middleware 1 end");
});
app.use(async (req, res, next) => {
console.log("middleware 2 start");
await next();
console.log("middleware 2 end");
});
app.use(async (req, res, next) => {
res.writeHead(200);
res.end("An request come in");
await next();
});
app.listen(3000, () => {
console.log("Server listen on port 3000");
});
上記のデモには三つの注意点があります。私たちは次のコードの中でこれらの使い方の原因を一つ一つ分析します。具体的にどのようにこのオニオンリング機構を実現するかを見てみます。
class Koa {
...
use(middlewareFn: middlewareFn) {
// 1、 use , middleware
this.middlewares.push(middlewareFn);
return this;
}
listen(port: number, cb: noop) {
// 2、 composeMiddleware [ ] , createServer
// composeMiddleware, ,
// BTW: fn listen , middleware
const fn = composeMiddleware(this.middlewares);
const server = http.createServer(async (req, res) => {
await fn(req, res);
});
return server.listen(port, cb);
}
}
// 3、 :
// :
// :
function composeMiddleware(middlewares: middlewareFn[]) {
return (req: IncomingMessage, res: ServerResponse) => {
let start = -1;
// dispatch: i
function dispatch(i: number) {
// ,
// start < i, next() start === i
// next(), start === i , start >= i
if (i <= start) {
return Promise.reject(new Error("next() call more than once!"));
}
if (i >= middlewares.length) {
return Promise.resolve();
}
start = i;
const middleware = middlewares[i];
// !!!
// i , dispatch(i+1) next
return middleware(req, res, () => {
return dispatch(i + 1);
});
}
return dispatch(0);
};
}
主にPromiseに関するいくつかの知識点:今私たちが振り返る前に提出したいくつかの問題:
next, dispatch(i+1), ,
next
第三ステップ:Contect提供
目標:パッケージングContect、request、reponseの便利な操作方式を提供する。
, await next(), next()【 】 ,
第四ステップ:非同期関数エラー処理メカニズムターゲット:ap.on(「error」)によるエラーイベントの処理異常の監視
私達はKooの中でどのように異常を処理するかを思い出します。コードは以下のようになるかもしれません。
// 1、 KoaRequest、KoaResponse、KoaContext
interface KoaContext {
request?: KoaRequest;
response?: KoaResponse;
body: String | null;
}
const context: KoaContext = {
get body() {
return this.response!.body;
},
set body(body) {
this.response!.body = body;
}
};
function composeMiddleware(middlewares: middlewareFn[]) {
return (context: KoaContext) => {
let start = -1;
function dispatch(i: number) {
// .. ..
// 2、 context
middleware(context, () => {
return dispatch(i + 1);
});
}
return dispatch(0);
};
}
class Koa {
private context: KoaContext = Object.create(context);
listen(port: number, cb: noop) {
const fn = composeMiddleware(this.middlewares);
const server = http.createServer(async (req, res) => {
// 3、 req、res context
// :context , this.context
// context , context
const context = this.createContext(req, res);
await fn(context);
if (context.response && context.response.res) {
context.response.res.writeHead(200);
context.response.res.end(context.body);
}
});
return server.listen(port, cb);
}
// 4、 context
createContext(req: IncomingMessage, res: ServerResponse): KoaContext {
// Object.create ?
// request、response、context
const request = Object.create(this.request);
const response = Object.create(this.response);
const context = Object.create(this.context);
request.req = req;
response.res = res;
context.request = request;
context.response = response;
return context;
}
}
上のコードからコアが見えます。具体的なコードはどうやって実現されますか?
app.use(async (context, next) => {
console.log("middleware 2 start");
// throw new Error(" ");
await next();
console.log("middleware 2 end");
});
// koa : error
app.on("error", (error, context) => {
console.error(` ${context.url} `);
});
締め括りをつけるこれまでType Scriptを使って、簡単版Kooaクラスライブラリを完成しました。サポートしました。
より多くの素晴らしい文章、皆様を歓迎します。私達は毎週いくつかの高品質の先端領域に関する文章を発表します。
参考資料