如何避免条件表达式中咖啡脚本中的隐式“返回”?

Posted

技术标签:

【中文标题】如何避免条件表达式中咖啡脚本中的隐式“返回”?【英文标题】:How to avoid an implicit "return" in coffeescript in conditional expressions? 【发布时间】:2013-03-06 08:41:06 【问题描述】:

我正在实现一个具有延迟返回值的函数,并且在函数内我有许多嵌套的条件表达式:

例如:

deferred = Q.defer()
FS.readFile("foo.txt", "utf-8", (error, text) ->
    if error
      deferred.reject(new Error(error))
    else
      deferred.resolve(text)
)
return deferred.promise

将被编译成:

var deferred;

deferred = Q.defer();

FS.readFile("foo.txt", "utf-8", function(error, text) 
  if (error) 
    --> return <-- deferred.reject(new Error(error));
   else 
    --> return <-- deferred.resolve(text);
  
);

return deferred.promise;

我只需要最后一个返回,而不需要 if/else 返回(即编译代码中的 --> return )

如何避免咖啡脚本编译器的这种行为(在不需要的地方隐式返回)?

【问题讨论】:

这不是您认为的问题。有问题的返回是从内部回调函数返回的。这是理想的行为,它不会以任何方式干扰您的外部函数的return 【参考方案1】:

Coffeescript 自动返回最后一个表达式的结果,所以如果你不希望它返回 if 的结果,那么你需要添加另一个表达式。在这种情况下,只需添加return

FS.readFile "foo.txt", "utf-8", (error, text) ->
  if error
    deferred.reject new Error(error)
  else
    deferred.resolve text
  return

另外,error 已经是一个Error 对象,所以你可以直接拒绝它。

deferred.reject(error)

【讨论】:

谢谢!它可以工作,但在我看来它将被编译为“if/else 表达式后跟 return();”而不是所有其他代码 @static 是的,没关系。 我的意思是它看起来对我来说会被编译成:var deferred; deferred = Q.defer(); FS.readFile("foo.txt", "utf-8", function(error, text) if (error) deferred.reject(new Error(error)); else deferred.resolve(text); ); return; return deferred.promise; 所以就像一个函数之后的两个返回 @static 你确定你的缩进是正确的吗?它绝对不应该那样出来。 好的,由于缩进,它将是函数中的一个返回和那里的一个返回。但是,我还是觉得有点奇怪……但真的,谢谢!【参考方案2】:

你不能,确切地说。您可以在不需要时忽略它们(这是最常见的做法),也可以通过在函数末尾添加附加语句来提供明确的替代方案。我认为在你的代码库中一直尝试这样做是在与你无法获胜的语言进行一场战争,所以我个人的建议是接受 Ashkenas 先生的隐含回报并继续你快乐的方式。

fs.readFile "foo.txt", "utf-8", (error, text) ->

  # postfix style if statement here avoids the else
  # of course, the value returned you may not like, so 
  # you probably won't use this style, but my boilerplate for
  # error handling is
  # return callback(error) if error

  return deferred.reject(new Error(error)) if error
  deferred.resolve(text)

  # Here you can add an explicit return like
  return

  # or some other expression
  null

  # or 'this' in cases where chainability might be nice
  this

  # or so you don't accidentally delete this statement later thinking it is
  # useless
  return null

这些形式中的任何一种都可以,但在实践中我不经常看到这些形式

【讨论】:

谢谢!用return语句遇到这样的情况,真的有点奇怪 它不熟悉,但随着时间的推移它会变得熟悉并且可能不会打扰您。我从未听过有经验的咖啡师提到这很麻烦。 因为不麻烦。内部返回没有暴露外部功能。忽略它们。 但是内在回报确实很重要。请参阅 programmaticallyspeaking.com/… 和 awardwinningfjords.com/2012/05/08/… 了解原因。 因为Coffeescript就是这样工作的,所以我养成了每次输入'->'和回车后立即输入'return'的习惯。【参考方案3】:

我总是这样:

f = ->
  deferred = Q.defer()
  FS.readFile ..., ( error, text ) ->
    return deferred.reject error if error?
    deferred.resolve text
  return deferred.promise

第一个return 用于停止执行,而不是返回值。

你仍然在你的 JS 中从回调的最后一行得到一个额外的(而且毫无意义的)return;为避免出现这种情况,请插入一个额外的 return null(如果您愿意,也可以直接插入 return)。

我不确定我是否喜欢 CoffeeScript 的隐式 return 插入;可能会声称“显式优于隐式”。此外,可以说第一个 return 不应该是 return 而是另一个关键字,例如 stopfinish 或类似的。

作为一个不相关的旁注,我在使用 Promise 时没有观察到任何明显的优势。相反,我发现它们在我的代码中非常具有侵入性,与那些 deferreds 和其他置于异步编程之上的概念有关。

【讨论】:

以上是关于如何避免条件表达式中咖啡脚本中的隐式“返回”?的主要内容,如果未能解决你的问题,请参考以下文章

Java 条件表达式结果的隐式转换

我的咖啡脚本中的条件语句在应该返回一个数字时返回一个布尔值[重复]

Scala 学习笔记之隐式参数和隐式转换并用

避免构造函数中的隐式转换。 'explicit' 关键字在这里没有帮助

Mysql中的隐式转换

mysql中的隐式类型转化及实际mysql说明