正直なところ、Promises/Futures/Deferreds/etc... または (/and) モデレーター (またはオブザーバー/サブパブ、ある特定のオブジェクトがデータのソースになる十分な理由がある場合)。
これは 100% の確率ではありません。コールバックが 1 つだけ必要な場合もあります。ただし、(モデル データ内の、またはユーザー インタラクションを視覚化するために) 変更に対応する必要がある複数のビューがある場合、ハードコードされた結果の束を含む単一のコールバックは適切ではありません。
moderator.listen("my-model:timeline_update", myView.update);
moderator.listen("ui:data_request", myModel.request);
button.onclick = function () { moderator.notify("ui:data_request", button.value); }
1 つの大きなコールバックへの依存度が大幅に低下し、コードを組み合わせて再利用できるようになりました。
モデレーターを隠したい場合は、オブジェクトの一部にすることができます:
var A = function () {
var sys = null,
notify = function (msg, data) {
if (sys && sys.notify) { sys.notify(msg, data); }
},
listen = function (msg, callback) {
if (sys && sys.listen) { sys.listen(msg, callback); }
},
attach = function (messenger) { sys = messenger; };
return {
attach : attach
/* ... */
};
},
B = function () { /* ... */ },
shell = Moderator(),
a = A(),
b = B();
a.attach(shell);
b.attach(shell);
a.listen("do something", a.method.bind(a));
b.notify("do something", b.property);
これが少し見慣れているように見える場合は、たとえば Backbone.js と同様の動作です (ただし、extend()
オブジェクトに対する動作であり、他のものはバインドされます。私の例では、何が起こっているかを示すためにラッパーを単純化しています)。
Promise は、使いやすさ、保守性、読みやすいコードのもう 1 つの大きな利点です (人々が "promise" とは何かを知っている限り、基本的には、コールバック サブスクリプションを持つオブジェクトを通過します)。
// using jQuery's "Deferred"
var ImageLoader = function () {
var cache = {},
public_function = function (url) {
if (cache[url]) { return cache[url].promise(); }
var img = new Image(),
loading = $.Deferred(),
promise = loading.promise();
img.onload = function () { loading.resolve(img); };
img.onerror = function () { loading.reject("error"); };
img.src = url;
cache[url] = loading;
return promise;
};
return public_function;
};
// returns promises
var loadImage = ImageLoader(),
myImg = loadImage("//site.com/img.jpg");
myImg.done( lightbox.showImg );
myImg.done( function (img) { console.log(img.width); } );
または var blog_comments = [ /* ... */ ],
comments = BlogComments();
blog_comments.forEach(function (comment) {
var el = makeComment(comment.author, comment.text),
img = loadImage(comment.img);
img.done(el.showAvatar);
comments.add(el);
});
約束がどれほど強力であるかを示すために、そこにあるすべてのクラフトがあります。そこの呼び出し
を見てください。.forEach
この場合はもう少し明白に見えるかもしれないので、AJAX の代わりに画像の読み込みを使用しています。
何百ものブログ コメントを読み込むことができます。同じユーザーが複数の投稿を行う場合、画像はキャッシュされます。そうでない場合は、画像が読み込まれるのを待つ必要も、ネストされたコールバックを記述する必要もありません。画像は任意の順序で読み込まれますが、適切な場所に表示されます。
これは、AJAX 呼び出しにも 100% 適用できます。