Я реализую функцию, которая имеет отложенное значение для возврата, и внутри функции у меня есть много вложенных условных выражений:
например:.
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 < - в скомпилированном коде)
Как я могу избежать такого поведения (неявные возвращения там, где они не нужны) компилятора coffeescript?
Ответ 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)
Ответ 2
Вы не можете, точно. Вы можете либо игнорировать их, когда они не нужны (что наиболее часто используется), либо предоставить явную альтернативу, добавив дополнительный оператор в конце функции. Я думаю, что попытка сделать это все время в вашей базе кода ведет борьбу против языка, который вы не можете выиграть, поэтому моя личная рекомендация просто принимает неявное возвращение г-на Ашкенаса и продолжает ваш веселый путь.
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
любая из этих форм будет работать, но на практике я не вижу их обычно
Ответ 3
Я всегда делаю это так:
f = ->
deferred = Q.defer()
FS.readFile ..., ( error, text ) ->
return deferred.reject error if error?
deferred.resolve text
return deferred.promise
первый return
должен остановить выполнение, а не возвращать значение.
вы по-прежнему получаете дополнительный (и бессмысленный) return
в своем JS из последней строки обратного вызова; чтобы избежать этого, добавьте дополнительный return null
(или просто return
, если вы этого захотите).
Я не уверен, что мне нравится неявная вставка в CoffeeScript; можно утверждать, что "явный лучше, чем неявный". Кроме того, можно утверждать, что первый return
не должен быть return
, а другим ключевым словом, например, stop
или finish
или somesuch.
как несвязанный боковой элемент, я не заметил никаких заметных преимуществ при использовании promises. напротив, я нашел их довольно навязчивыми в своем коде, что с этими deferred
и другими понятиями, которые ставятся поверх асинхронного программирования.