【问题标题】:NodeJS default parameter when last parameter is the callback最后一个参数是回调时的NodeJS默认参数
【发布时间】:2015-11-19 13:12:47
【问题描述】:

我有一个类似这样的功能(简化):

doSmthg (name, age, callback) {
  callback(name, age);
}

如果没有提供年龄,我希望有一个默认值。

我知道我可以在 ES6 中使用 doSmthg(name, callback, age=42) {...},但我被告知 callback 应该始终是最后一个参数,因为它使对函数的调用更具可读性。

目前我找到的解决方案是执行以下操作:

doSmthg (name, age, callback) {
  if (arguments.length === 2) {
    age = 42;
    callback = age;
  }
}

但我觉得这个解决方案很难阅读。

这是好的解决方案吗?有更好的吗?

【问题讨论】:

  • 使用 Promise 是一种选择吗?
  • @robertklep 我从未在这个项目中使用过 Promise。如果它导致一个非常“酷”的解决方案,我可以考虑使用承诺,但我宁愿不
  • 您的函数声明将如下所示:doSmthg(name, age = 42)(因为您不再需要传递回调)。
  • @robertklep 我会看看这个。谢谢你:)
  • 我肯定会建议使用 Promise。它们是 ES6 中的一流语言结构,并且比回调更好。在几乎每个对我有回调的库中,最终都会对bluebird 产生“隐形”依赖,因为我必须承诺一切。

标签: javascript node.js ecmascript-6


【解决方案1】:

对于这种情况,你可以使用这样的东西:

function doSmthg(name, age, callback) {
  if (typeof age === 'function') {
    callback = age;
    age = DEFAULT_VALUE;
  }
  //continue
}

或者你可以使用选项的哈希,我认为它更好,因为使代码更具可读性,具体取决于参数的数量:

function doSmthg(options, callback) {
  var name = options.name;
  var age = options.age || DEFAULT_VALUE;
  //continue
}

doSmthg({ name: 'batman' }, function() {});

您也可以使用underscore #extend function 将选项与默认值合并。

【讨论】:

  • 请注意,如果您使用的是 ES6(似乎是 OP),您可以用解构赋值替换您的选项对象。这不会改变调用者的观点,但从被调用者的角度来看,它更具可读性。 doSmthg({name, age = DEFAULT_VALUE}, callback).
【解决方案2】:

如果您可以访问传播运算符:

function foo(...args) {
  const callback = args.pop();
  const [name, age = 42] = args;
  // ...  
}

但我认为也是时候在 NodeJS 中使用 Promise 了。

function foo(name, age = 42) {
  return new Promise(resolve => {
    setTimeout(() => resolve({name, age}), 1000);
  });
}
//...
foo('Sándor').then(x => console.log(x)); // { name:"Sándor", age:42 }

使用 ES6 承诺您可以摆脱所谓的“回调金字塔”,并使您的函数与 ES7 async-await 关键字一起使用成为可能。未来已来!

【讨论】:

    【解决方案3】:

    代码

    function foo(args, callback){
        parsed = {name:"John Doe",age:12};      //default values
        for(a in args) parsed[a] = args[a];
    
        //Arguments are accessible like parsed.name
    
        callback(parsed);
    }
    
    function callback(args){
        alert(JSON.stringify(args));
    }
    
    
    foo({name:"Peter",extra:2},callback);//yields {"name":"Peter","age":12,"extra":2}
    foo({name:"Mark",age:92},callback);  //yields {"name":"Mark","age":92}
    foo({},callback);                    //yields {"name":"John Doe","age":12}
    

    说明

    根据要传递的参数数量,它可能看起来过于冗长,不符合您的喜好。这个概念应该是不言自明的,但是用文字来说,我们将参数分组到一个对象中,并且在函数内部有一个具有默认值的对象(如果需要)。然后我们用传递的参数覆盖默认值,留下一个非常清晰的callback 和详细的参数。

    请注意,如果传递了额外的参数,这些参数在设置默认值的过程中不会丢失。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-22
      • 2018-07-20
      • 2011-11-04
      • 2010-11-15
      • 2012-08-07
      • 1970-01-01
      • 2016-02-14
      • 2017-01-28
      相关资源
      最近更新 更多