7

单看我现在写的,我可以看到一个小得多,所以在代码方面高尔夫 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);
    }
});
4

4 回答 4

6

它们并不完全相同。选项 2 仍将记录(数据),而选项 1 只会记录成功的数据。(编辑:至少在您更改代码之前是这样的)

也就是说,选项 1 更具可读性。编程不是/不应该是一场比赛,看谁能写出最少的代码来完成最多的事情。目标应该始终是创建可维护、可扩展(如有必要)的代码——以我的拙见。

于 2012-12-20T04:14:58.797 回答
2

许多人会发现选项#1 更易于阅读和维护——两个不同的回调函数用于两个不同的目的。它被所有Promise Libraries常用,其中将传递两个参数。当然,Multiple arguments vs. options object的问题是独立的(虽然该对象在 中有用jQuery.ajax,但对 没有意义promise.then)。

但是,选项#2 是Node.js 约定(另请参见NodeGuide)并在许多受其影响的库中使用,例如著名的async.js。然而,这个约定是可以讨论的,我发现的顶级谷歌结果是WekeRoad:NodeJS回调约定Stackoverflow:Node.js 库的建议回调样式是什么?.

单个回调函数带有错误参数的原因是它总是提醒开发人员处理错误,这在服务器端应用程序中尤为重要。许多客户端ajax函数的初学者并不关心错误处理,例如,问自己为什么没有调用成功回调。另一方面,带有then-chaining 的 Promise 是基于错误回调的可选性,将它们传播到下一个级别——当然它仍然需要在那里被捕获。

于 2012-12-20T04:43:12.353 回答
0

老实说,我更喜欢让它们更进一步,进入 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 调用。

于 2012-12-20T05:40:20.437 回答
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)
  }
}
于 2016-04-08T01:53:49.857 回答