フロントエンドPromiseチェーン呼び出しの代わりにKoaミドルウェアに基づく
37162 ワード
文書ディレクトリ まずいくつかのキーワード を理解します問題シーン 実現一:流水式処理 実装2:Promiseチェーンコール 分割フォーム発行時に処理する各サブロジック 各サブロジックを`submit`関数にまとめる
実現三:挿抜可能なミドルウェアモード を使用 1. `koa-compose`が提供する`compose`関数を直接参照して、私たちが提供するミドルウェア を組み合わせます. 2. `Koa`のようなミドルウェア管理メカニズムおよびエントリ実行メカニズム を提供する 3. 具体的には を用いる. 4. 最初の質問シーン と組み合わせる
まずいくつかのキーワードを理解します Koaミドルウェアとその玉ねぎリングモデル koa-compose よく見られる中間部品の原理浅析 Promiseチェーンコール Promiseチェーンコール
質問シーン
大きなフォームページがあると仮定し、フォームをコミットする前に以下のことをする必要があります.フォームフィールドチェック(メールボックスフォーマットチェックなど) 個別フィールドの機密語チェック フィールド名またはフィールド値フォーマット処理(時間フォーマットなど) をコミットする.バックエンド にデータをコミットする.
以下,それぞれ3つの異なる実装方式を分析する.
実現一:流水式処理
実装2:Promiseチェーン呼び出し
フォームの発行時に処理するサブロジックの分割
各サブロジックを各サブプロセッシングロジックを抽出して後期にメンテナンスし、submit関数に対する汚染を低減する . Promiseチェーン呼び出しにより、コミットプロセス全体がより制御可能になる 同時に以下の問題を引き起こす.新しいサブプロセッシングロジックを追加するには を修正する必要がある.サブプロセッシングロジックの順序を調整するには、 を修正する必要がある.
実現三:挿抜可能なミドルウェアモードを使用する
1.
2.
3.具体的な使用
4.最初の質問シーンに合わせる
これまでの新しいサブプロセッシングロジックを追加するには 件の問題を解決します.サブプロセッシングロジックの順序を調整するには を調整する必要がある.
サブ処理ロジックは
まずいくつかのキーワードを理解します
質問シーン
大きなフォームページがあると仮定し、フォームをコミットする前に以下のことをする必要があります.
以下,それぞれ3つの異なる実装方式を分析する.
実現一:流水式処理
// 4
const submit = () => {
/**
* 1.
*
*/
if (!formValid) {
return false;
}
/**
* 2.
*
*/
if (!sensitiveValid) {
return false;
}
/**
* 3.
*
*/
formFields.format();
/**
* 4.
*
*/
formFields.submit();
};
submit
関数は4つの異なる処理ロジックを含み、これにより他の処理ロジックを記入することが困難になり、後期メンテナンスコストが高く、同時に開閉原則に違反する.実装2:Promiseチェーン呼び出し
フォームの発行時に処理するサブロジックの分割
let formValidPromise = new Promise((resolve, reject) => {
/**
* 1.
*
*/
if (formValid) {
resolve(true);
} else {
resolve(false);
}
});
let sensitiveValidPromise = new Promise((resolve, reject) => {
/**
* 2.
*
*/
if (sensitiveValid) {
resolve(true);
} else {
resolve(false);
}
});
let formFormatPromise = new Promise((resolve, reject) => {
/**
* 3.
*
*/
resolve(true);
});
let formSubmitPromise = new Promise((resolve, reject) => {
/**
* 4.
*
*/
formFields.submit();
resolve(true);
});
各サブロジックを
submit
関数にまとめるconst submit = () => {
//
formValidPromise().then((isValid) => {
if (isValid) {
return formValidPromise();
}
return reject({
formValid: false
});
}).then((sensitiveValid) => {
if (sensitiveValid) {
return sensitiveValidPromise();
}
return reject({
sensitiveValid: false
});
}).then(() => {
return formFormatPromise();
}).then(() => {
return formSubmitPromise();
}).catch(error => {
console.log('error: ', error);
});
};
const submit = async () => {
// async/await
try {
await formValidPromise();
await sensitiveValidPromise();
await formFormatPromise();
await formSubmitPromise();
} catch(error) {
// reject
console.log('error: ', error);
}
};
submit
関数submit
関数実現三:挿抜可能なミドルウェアモードを使用する
1.
koa-compose
によって提供されたcompose
関数を直接参照し、我々が提供したミドルウェアを組み合わせる/**
* Compose `middleware` returning
* a fully valid middleware comprised
* of all those which are passed.
*
* @param {Array} middleware
* @return {Function}
* @api public
*/
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!')
}
/**
* @param {Object} context
* @return {Promise}
* @api public
*/
return function (context, next) {
// last called middleware #
let index = -1
return dispatch(0)
function dispatch (i) {
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 {
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
} catch (err) {
return Promise.reject(err)
}
}
}
}
2.
Koa
のようなミドルウェア管理機構及び入口実行機構を提供する//
class Middleware {
constructor () {
this.middleare = [];
}
use(fn) {
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
this.middleware.push(fn);
return this;
}
init() {
//
const fn = compose(this.middleware);
const dispatch = () => {
//
const ctx = Object.create(null);
return this.dispatch(ctx, fn)
}
return dispatch;
}
dispatch(ctx, fnMiddleware) {
return fnMiddleware(ctx).then(() => {
//
console.log('ctx: ', ctx);
}).catch((error) => {
console.log(error);
});
}
}
export default Middleware;
3.具体的な使用
let middleware = new Middleware();
middleare.use(async (ctx, next) => {
console.log('ctx1: ', ctx);
await next();
});
middleare.use(async (ctx, next) => {
console.log('ctx2: ', ctx);
await next();
});
let dispatch = middleware.init();
dispatch() //
4.最初の質問シーンに合わせる
let formValidMd = async (ctx, next) => {
/**
* 1.
*
*/
if (formValid) {
ctx.formValid = true;
await next();
} else {
ctx.formValid = false;
}
};
let sensitiveValidMd = async (ctx, next) => {
/**
* 2.
*
*/
if (sensitiveValid) {
ctx.sensitiveValid = true;
await next();
} else {
ctx.sensitiveValid = false;
}
};
let formFormatMd = async (ctx, next) => {
/**
* 3.
*
*/
ctx.formFormat = true;
await next();
};
let formSubmitMd = async (ctx, next) => {
/**
* 4.
*
*/
formFields.submit();
ctx.formSubmit = true;
await next();
};
// , use
let middleware = new Middleware();
middleare.use(formValidMd);
middleare.use(sensitiveValidMd);
middleare.use(formFormatMd);
middleare.use(formSubmitMd);
let dispatchSubmit = middleare.init();
submit
の関数実装を見てみましょうconst submit = () => {
dispatchSubmit();
}
これまでの
submit
関数ではコードが少なくなりました
で解決すべき問題を振り返ってみましょうsubmit
の関数を修正する必要があります->サブロジックプロセッシングミドルウェアを追加するだけで、use
はsubmit
の関数を修正する必要がある->現在順序を変更するには、ミドルウェアuse
の前後関係サブ処理ロジックは
submit
関数と完全にデカップリングされ,開放閉鎖設計の原則に合致した.書くコードはもとは多くなりましたが、メンテナンスコストもずいぶん下がって、具体的に需要のあるシーンを取捨選択して、具体的に分析して、具体的に解決します.