【问题标题】:What's the best practice for function callback structure? [closed]函数回调结构的最佳实践是什么? [关闭]
【发布时间】:2011-11-23 15:01:09
【问题描述】:

哪种函数回调结构最适合在 Javascript 中使用,为什么?我已经看到这两个选项使用了很多。还有吗?


选项 A:

// DECLARATION
function funcA(required, success, error, options){

  // if there is an error in your function return 
  // and run error function
  if(errorHappens){ return error('an error') };

  // if no error happened: run the success function
  success('all good here is your var back', required);
}

// USAGE
funcA('this is required', function(result){

  // all good, do something with the result :)

},
function(error){

  // tell the user about the error
  alert('error happened')  
},{
  optionalThing: ':-)'
});


选项 B:

// DECLARATION
function funcB(required, callback, options){

  // if an error happens run the single callback with
  // the err param populated and return
  if(errorHappens){ return callback('an error') };

  // if no error happened: run the callback with 'null'
  // as the error param.
  callback(null, 'this is a result');
}

.

// USAGE
funcB('this is required', function(err, result){
  if(err){ return alert('error happened') };

  // all good do something with the result :)

},{
  optionalThing: ':-)'
}

【问题讨论】:

  • +1 看不出这是“没有建设性”的原因

标签: javascript function coding-style


【解决方案1】:

这取决于环境,对于 node.js

我个人建议你坚持回调作为最后一个参数

function doSomething(data, options, cb) {
  ...
  if (err) return cb(err);
  cb(null, result);
}

doSomething(data, { ... }, function (err, data) {
    if (err) throw err;
    ...
});

主要是因为这是节点社区中使用的编码风格。如果您根本不与 node.js 交互,那么您可能应该使用与您交互的环境最常见的样式。

如果您的环境主要围绕 jQuery,那么我只会从您的 doSomething 函数返回一个 $.Deferred 对象

function doSomething(data, options) {
  return $.Deferred();
}

$.when(
  doSomething(data, { ... })
).then(
  function () { /* success */ },
  function () { /* error */ }
);

编辑:

function doSomething(data, options, cb) {
  if (typeof options === "function") {
    cb = options;
    options = null;
  }
  ...
}

【讨论】:

  • 这是否意味着您必须在中间有一个空哈希才能进行没有选项的调用?
  • @pagewil 不,这是一个可选参数。使用您的标准可选参数逻辑。或者你让第一个参数是一个哈希,第二个是一个回调,这完全取决于你的 API 是什么。
  • 没有它,为什么cb() 不代替options 作为第二个参数?
  • @pagewil 确实如此。所以你可以称它为doSomething(data, cb)doSomething(data, hash, cb)。我推荐最后的回调样式,因为节点社区的每个人都这样做。
  • 你应该在函数内部使用什么代码来解释这个可选参数顺序?
【解决方案2】:

你选择什么并不重要。我更喜欢 B,因为我可以在不更改函数定义的情况下添加更多错误代码。

您还可以使用另一种模式,其中您的“回调”是函数{error: function(){}, success: function(){}} 的散列。而且这在 JS 库中是可扩展的并且很常见。

【讨论】:

  • 有趣的谢谢 :) 如果您将选项 C 添加到问题中,那就太好了(我会批准编辑)
【解决方案3】:

我更喜欢以如下形式传递对象字面量:

var callback = {
    success : function(){},
    error : function(){},
    complete : function(){}
};

并以这种方式使用它:

function(callback){
    try{
        /*...processing...*/
        if(success)
            typeof callback.success === 'function' && callback.success(result);
        else 
            throw new Error('unsuccesfull');
    }catch(err){
        typeof callback.error === 'function' && callback.error(err.message);
    }finally{
        typeof callback.complete === 'function' && callback.complete() || typeof callback === 'function' && callback();
    }
}

主要优点是这样,我可以为每个结果状态提供回调,而且我可以省略任何我想要的状态回调。我什至可以只传递一个函数(而不是一个对象),它相当于complete 回调。

【讨论】:

  • 那很难看。这清楚地表明您的对象应该是事件发射器或事件目标,因此您可以this.emit("success", result)
【解决方案4】:

都没有。

我更喜欢带有散列参数的全功能版本,以及使用“通用”参数作为参数的快捷方法。

哪个最有意义取决于相关函数的使用模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 2020-06-26
    • 2010-09-07
    • 2019-10-21
    • 1970-01-01
    • 2011-09-30
    相关资源
    最近更新 更多