ホームページ > 記事 > ウェブフロントエンド > JavaScript のノードミドルウェアの原理を簡単に理解する
関連する無料学習の推奨事項: javascript(ビデオ)
ミドルウェアとは、アプリケーションシステムとシステムソフトウェアの間にあるソフトウェアの一種で、システムソフトウェアが提供する基本的なサービス(機能)を利用してネットワークに接続するものです。アプリケーションシステムまたは異なるアプリケーションは、リソース共有と機能共有の目的を達成できます。
NodeJS における Middleware は、主に http リクエストの詳細処理をカプセル化する方法を指します。 http リクエストには、次のような多くのアクションが含まれることがよくあります。
Web アプリケーションの場合、詳細な処理の代わりに、すべてを知りたくないのです。開発効率を向上させるためにビジネス開発に集中したいと考えているため、これらの基本的なロジック処理の詳細を簡素化してカプセル化するために ノード ミドルウェアを導入します。 #本質的には、特定のビジネス処理に入る前に 特定のフィルター
を処理できるようになります。以下の図に示すように:現在主流の nodejs フレームワーク (connect、koa
、express、 egg、nest などはミドルウェアの設計思想と切り離せないものなので、nodejs の世界を誰もがより深く覗けるよう、実装を比較検討しました。 ##本文ノードミドルウェアの概念を理解した後、手動でミドルウェアを実装し、最後にkoaにおけるミドルウェアの実装アイデアを簡単に分析します。
ノード ミドルウェアのコア原則の実装koa ミドル キーの実装方法koa ミドルウェア メカニズムを使用して独自の koa ミドルウェアを実装するconst middleware = (req, res, next) => { // 请求处理逻辑 next() }复制代码
// 定义几个中间间函数const m1 = (req, res, next) => { console.log('m1 run') next() }const m2 = (req, res, next) => { console.log('m2 run') next() }const m3 = (req, res, next) => { console.log('m3 run') next() }// 中间件集合const middlewares = [m1, m2, m3]function useApp (req, res) { const next = () => { // 获取第一个中间件 const middleware = middlewares.shift() if (middleware) { middleware(req, res, next) } } next() }// 第一次请求流进入useApp()复制代码
m1 run m2 run m3 run复制代码上記の内容は次のとおりです。基本的なミドルウェアの実行モードを実現しましたが、非同期性の問題も考慮する必要があります。ミドルウェアが検証、識別、その他のサービスなどのサードパーティ モジュールまたは API のサポートにも依存している場合は、次を実行する必要があります。次のコードに示すように、非同期ミドルウェアのコールバック内で通常の呼び出し実行シーケンスを保証します:
const m2 = (req, res, next) => { fetch('/xxxxx').then(res => { next() }) }复制代码ログ ミドルウェアやリクエスト モニタリング ミドルウェアなどのミドルウェア シナリオもあり、関連するロジックが実行されます。このとき、関数が二次処理を行う際に、next の戻り値を
promise にラップすることで、next
ができるようにする必要があります。ビジネス処理が完了した後も、then
コールバックを通じてミドルウェア ロジックの処理を続行できます。以下に示すように:function useApp (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { // 将返回值包装为Promise对象 return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("end") } } next() }复制代码この時点で、次の方法で呼び出すことができます:
const m1 = (req, res, next) => { console.log('m1 start') return next().then(() => { console.log('m1 end') }) }复制代码上記では、基本的なミドルウェア設計パターンを実装しました。もちろん、async と await を使用して実装することもできます。書き方はより洗練され、シンプルになります。作成者による簡単な例を次に示します:
const m1 = async (req, res, next) => { // something... let result = await next(); } const m2 = async (req, res, next) => { // something... let result = await next(); } const m3 = async (req, res, next) => { // something... let result = await next(); return result; }const middlewares = [m1, m2, m3];function useApp (req, res) { const next = () => { const middleware = middlewares.shift() if (middleware) { return Promise.resolve(middleware(req, res, next)) }else { return Promise.resolve("end") } } next() }// 启动中间件useApp()复制代码koa2 フレームワークでは、next() メソッドの戻り値を Promise オブジェクトにカプセル化することでミドルウェアも実装され、以下に示すように、提案されたオニオン リング モデルを実現します。 #koa ミドルウェア実装方法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) { // 防止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) } } } }复制代码
学习了中间件的设计机制和原理, 我们是不是想马上写一个中间件呢? 笔者这里给大家举一个例子. 在H5-Dooring项目的服务端代码中, 我们需要对用户登录权限进行分发, 此时我们提供统一个中间件来处理, 如下代码所示:
// 模拟数据库操作const token = db.user();// router或者koa的中间件一定要用await处理next,否则将不能正常响应数据export default async (ctx, next) => { const t = ctx.request.header.authorization let uid = ctx.request.header['x-requested-with'] let uidArr = uid.split(',') if(uidArr.length > 1) { uid = uidArr.pop().trim() } if(token[uid] && token[uid][1] === t) { await next() }else { ctx.status = 403; ctx.body = { state: 403, msg: '你没有权限操作' } } }复制代码
以上代码即实现用户登录态处理, 如果用户在没有登录的情况下防问任何需要登录的接口, 都将返回权限不足或则在请求库中让其重定向到登录页面.
所以, 今天你又博学了吗?
以上がJavaScript のノードミドルウェアの原理を簡単に理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。