JavaScriptは非同期処理が基本の言語です。
非同期処理が基本であるがゆえ、同期的な言語では書けないような効率的なコードを書くことができます。
ですが、非同期処理は結果をコールバックで扱うためいわゆるコールバック地獄
に陥りがちです。
これはPromise
という仕組みを使うと少し楽ができます。
参考: Promiseと仲良くなって気持ち良く非同期処理を書こう
さて、ここからが本題。
JavaScriptのライブラリ作者の方にお願いがあります。
非同期処理を含む関数(メソッド)を書いたとき、戻り値に迷ったらPromiseをreturnしてほしい! ということです。
例えばJavaScriptの汎用バリデータライブラリであるvalidatorjs
では、カスタムルールとして非同期処理(例: DBに問い合わせを行ってユーザ名の重複をチェックする)を含むルールを作成することができます。
https://github.com/skaterdav85/validatorjs#asynchronous-validation
ところがcheck()
メソッドがこのルールに対応していません。わざわざcheckAsync()
という別メソッドを準備して非同期的ルールを処理しています。
もしcheck()
メソッドがpromiseを返していれば、非同期ルールがあるないに関わらず
var v = new Validator(/* data */, /* rules */);
v.check()
.then(function(){
// validation が通った場合
})
.catch(function(){
// validation に失敗した場合
});
のような書き方ができます。
各ルールはtrue/false(同期的ルール)かPromise(非同期的ルール)をreturnする。ということにすれば、check()
メソッドは以下のように統一的に実装できます。
- とりあえず新規に
Promise
をreturnする。(*) - ルールを評価する。
- Promiseを返すルールがあった場合は
Promise.all()
でそれらの結果を待つ。 - 全てのルールの結果が揃ったら、(*)のPromiseに対して
resolve()
またはreject()
をコール。
数年前に自分用に書いたバリデーションライブラリでは(jQueryのPromiseベースですが)同じようなことをやってました。
時間があったらvalidatorjsを改造してみたいと思います。
同じようなリファクタリングをした人もいるみたいです。 https://github.com/skaterdav85/validatorjs/issues/106
次のバージョンではこのアプローチを採用してほしいところですね。