只是看到我现在写的东西,我可以看到一个小得多,所以就code golf Option 2
来说是更好的选择,但就哪个更干净,我更喜欢Option 1
。我真的很喜欢社区对此的意见。
选项1
something_async({
success: function(data) {
console.log(data);
},
error: function(error) {
console.log(error);
}
});
选项2
something_async(function(error,data){
if(error){
console.log(error);
}else{
console.log(data);
}
});
答案 0 :(得分:6)
它们并不完全相同。选项2仍将记录(数据),而选项1仅记录成功数据。 (编辑:至少在更改代码之前就是这样)
那就是说,选项1更具可读性。编程不是/不应该是一个竞争,看谁能写出做最多事情的最少的线。我的目标应该始终是创建可维护的,可扩展的(如果必要的)代码 - 以我的拙见。
答案 1 :(得分:2)
许多人会发现选项#1更易于阅读和维护 - 两种不同的回调函数可用于两种不同的目的。它通常由所有Promise Libraries使用,其中将传递两个参数。当然,问题Multiple arguments vs. options object与此无关(虽然该对象在jQuery.ajax
中很有用,但对promise.then
没有意义。)
但是,选项#2是Node.js convention(另请参阅NodeGuide)并在许多受其影响的库中使用,例如着名的async.js。但是,这个约定是可以讨论的,我发现的最高谷歌搜索结果是WekeRoad: NodeJS Callback Conventions和Stackoverflow: What is the suggested callback style for Node.js libraries?。
带有错误参数的单回调函数的原因是它总是提醒开发人员处理错误,这在服务器端应用程序中尤其重要。许多初学者在客户端ajax函数不关心忘记错误处理,例如,问自己为什么不调用成功回调。另一方面,then
- 链接的承诺是基于错误回调的可选性,将它们传播到下一个级别 - 当然它仍然需要被捕获。
答案 2 :(得分:0)
说实话,我更倾向于将它们更进一步,进入Promises / Futures / Deferreds / etc ...... 或者(/和)使用主持人(或观察者/子酒吧)进入“自定义事件”队列,如果有充分理由让一个特定对象 源 < / strong> for data)。
这不是百分之百的时间。有时,您只需要一次回调。但是,如果您有多个视图需要对更改做出反应(在模型数据中,或者可视化用户交互),那么使用一堆硬编码结果的单个回调是不合适的。
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将是可用性,可维护性和易读性代码的另一个重大胜利(只要人们知道“承诺”是什么 - 基本上它传递了一个具有回调订阅的对象。)
// 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
电话。
我正在使用Image加载而不是AJAX,因为在这种情况下它似乎更明显:
我可以加载数百个博客评论,如果同一个用户发多个帖子,图像被缓存,如果没有,我不必等待加载图像,或编写嵌套回调。图像以任何顺序加载,但仍然出现在正确的位置。
这也是100%适用于AJAX调用。
答案 3 :(得分:0)
Promises
已被证明是异步的方式,像bluebird
这样的库包含节点式回调(使用(err, value)
签名)。因此,利用节点式回调似乎是有益的。
但问题中的示例可以通过以下函数轻松转换为任一格式。 (另)
function mapToNodeStyleCallback(callback) {
return {
success: function(data) {
return callback(null, data)
},
error: function(error) {
return callback(error)
}
}
}
function alterNodeStyleCallback(propertyFuncs) {
return function () {
var args = Array.prototype.slice.call(arguments)
var err = args.shift()
if (err) return propertyFuncs.err.apply(null, [err])
return propertyFuncs.success.apply(null, args)
}
}