函数回调结构的最佳实践是什么?

What's the best practice for function callback structure?

本文关键字:是什么 最佳 回调 结构 函数      更新时间:2023-09-26

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


选项:

// 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: ':-)'
}

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

我个人建议你坚持把callback作为最后一个参数

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;
  }
  ...
}

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

你也可以使用另一种模式,其中你的"回调"是函数{error: function(){}, success: function(){}}的哈希。

我更喜欢以这样的形式传递对象文字:

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回调。

都不是

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

哪个最有意义取决于所讨论的函数的使用模式。