老实说,我更喜欢让它们更进一步,进入 Promises/Futures/Deferreds/etc... 或者(/和)进入“自定义事件”队列,使用主持人(或观察者/子发布如果有充分的理由让某个特定对象成为数据源)。
这不是 100% 的时间。有时,您只需要一个回调。但是,如果您有多个视图需要对更改做出反应(在模型数据中,或可视化用户交互),那么带有一堆硬编码结果的单个回调是不合适的。
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); }
现在事情不再依赖于一个大回调,您可以混合、匹配和重用代码。
如果要隐藏版主,可以将其作为对象的一部分:
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 将是可用性、可维护性和易于阅读代码的另一个大赢家(只要人们知道“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,因为在这种情况下它可能看起来更明显:
我可以加载数百条博客评论,如果同一个用户发了多个帖子,则图像被缓存,如果没有,我不必等待图像加载,或者编写嵌套回调。图像以任何顺序加载,但仍出现在正确的位置。
这也 100% 适用于 AJAX 调用。