nodejsにおいてミドルウェアとは主にHTTPリクエスト全体の詳細な処理をカプセル化したメソッドを指し、HTTPリクエストの開始からレスポンスの終了までの処理メソッドを指します。ミドルウェアの動作は、特定のビジネス処理に入る前にフィルターに処理させるという Java のフィルターの動作原理に似ています。
このチュートリアルの動作環境: Windows7 システム、nodejs バージョン 12.19.0、Dell G3 コンピューター。
NodeJS では、ミドルウェアとは主に、すべての Http リクエストの詳細をカプセル化するメソッドを指します。 HTTP リクエストには通常、ロギング、IP フィルタリング、クエリ文字列、リクエスト本文の解析、Cookie 処理、権限の検証、パラメータの検証、例外処理などの多くの作業が含まれますが、Web アプリケーションの場合、これらの作業は不要です。開発効率の向上という目的を達成するために、開発者がビジネス開発に集中できるように、これらのインフラストラクチャとビジネスロジックの間の詳細を簡素化および分離するためにミドルウェアが導入されます。
ミドルウェアの動作は、特定のビジネス処理に入る前にフィルターに処理させるという Java のフィルターの動作原理に似ています。その動作モデルを次の図に示します。
ミドルウェア作業モデルconst middleware = (req, res, next) => { // TODO next() }
方法 1
次のように 3 つの単純なミドルウェアを定義します。const middleware1 = (req, res, next) => { console.log('middleware1 start') next() } const middleware2 = (req, res, next) => { console.log('middleware2 start') next() } const middleware3 = (req, res, next) => { console.log('middleware3 start') next() }
// 中间件数组 const middlewares = [middleware1, middleware2, middleware3] function run (req, res) { const next = () => { // 获取中间件数组中第一个中间件 const middleware = middlewares.shift() if (middleware) { middleware(req, res, next) } } next() } run() // 模拟一次请求发起
middleware1 start middleware2 start middleware3 start
next() メソッドを呼び出す必要があります。そうしないと、ミドルウェアを順番に実行できません。 middleware2 ミドルウェアを書き換えます:
const middleware2 = (req, res, next) => { console.log('middleware2 start') new Promise(resolve => { setTimeout(() => resolve(), 1000) }).then(() => { next() }) }
middleware1 start middleware2 start middleware3 start
next() が非同期操作の場合、現在のミドルウェアの他のコードをコールバックとして実行できません。したがって、
next() メソッドの後続の操作は
Promise オブジェクトにカプセル化でき、
next.then() フォームはその内部で使用できます。ミドルウェアが業務処理を完了するまでのコールバック。
run() メソッドを次のように書き換えます:
function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) } } next() }
const middleware1 = (req, res, next) => { console.log('middleware1 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 return next().then(() => { console.log('middleware1 end') }) }
const middleware1 = (req, res, next) => { console.log('middleware1 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 return next().then((res) => { console.log("1",res) return 'middleware1 end'; }) } const middleware2 = (req, res, next) => { console.log('middleware2 start') // 所有的中间件都应返回一个Promise对象 // Promise.resolve()方法接收中间件返回的Promise对象,供下层中间件异步控制 // console.log("next()",next()) return next().then((res) => { console.log("2",res) return 'middleware2 end' }) } const middleware3 = (req, res, next) => { console.log('middleware3 start') return next().then((res) => { console.log("3",res) return 'middleware3 end' }) } const middlewares = [middleware1, middleware2, middleware3]function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // console.log("next",next) // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("结束"); } } next() } run() // 模拟一次请求发起
async await 実装
const middleware1 = async (req, res, next) => { console.log('middleware1 start') let result = await next(); console.log("1",result) } const middleware2 = async (req, res, next) => { console.log('middleware2 start') let result = await next(); console.log("2",result) return 'middleware2 end'; } const middleware3 = async (req, res, next) => { console.log('middleware3 start') let result = await next(); console.log("3",result) return 'middleware3 end'; } const middlewares = [middleware1, middleware2, middleware3] function run (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // console.log("next",next) // 将middleware(req, res, next)包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("结束"); } } next() } run() // 模拟一次请求发起
フレームワークでは、ミドルウェアは方法 1 で実装され、グローバル ミドルウェアと組み込みルーティング ミドルウェア内のリクエスト パスに従って定義されたミドルウェアが連携しますが、それらは連携します。業務で使用できない 処理が完了すると、現在のミドルウェアのコードが呼び出されます。 koa2
フレームワークにおけるミドルウェアの実装方法は方法2であり、next()
メソッドの戻り値をPromise
にカプセル化し、以降の非同期処理を容易にします。は、koa2
フレームワークによって提案されたオニオン リング モデルを実装します。つまり、ミドルウェアの各層は球に相当します。モデル全体を貫通する場合、各球は実際には 2 回貫通します。
koa2 ミドルウェア オニオン リング モデル
koa2フレームワークのミドルウェア メカニズムは非常にシンプルかつエレガントです。フレームワークについては、こちらをご覧ください。 . 複数のミドルウェアを組み合わせるコアコード。 function compose (middleware) {
if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')
for (const fn of middleware) {
if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')
}
return function (context, next) {
let index = -1
return dispatch(0)
function dispatch (i) {
// index会在next()方法调用后累加,防止next()方法重复调用
if (i <= index) return Promise.reject(new Error('next() called multiple times'))
index = i
let fn = middleware[i]
if (i === middleware.length) fn = next
if (!fn) return Promise.resolve()
try {
// 核心代码
// 包装next()方法返回值为Promise对象
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
// 遇到异常中断后续中间件的调用
return Promise.reject(err)
}
}
}
}
ミドルウェアを実装する場合、単一のミドルウェアは十分にシンプルであり、単一の責任を持つ必要があります。各リクエストはミドルウェア関連のコードを呼び出すため、ミドルウェア コードは効率的であり、必要に応じて繰り返し取得したデータをキャッシュできる必要があります。異なるルートにミドルウェアを使用する場合は、異なるルートに異なるミドルウェアが適用されることも考慮する必要があります。
[推奨学習:「nodejs チュートリアル 」]
以上がNodejsにおけるミドルウェアとは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。