2013-03-18 1 views
12

Я реализую функцию, которая имеет отсроченное значение для возврата и в функции У меня есть много вложенных условных выражений:Как избежать неявного «возврата» в coffeescript в условных выражениях?

например:

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?

+2

Это не проблема, о которой вы думаете. Возвращенные данные возвращаются из внутренней функции обратного вызова. Это желательно поведение, и оно никак не мешает «возврату» вашей внешней функции. – meagar

ответ

12

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) 
+0

Спасибо!Он работает, но он выглядит так, как будто он будет скомпилирован в выражении if/else, следующего за return(); " и все остальные коды – static

+0

@static Да, и все в порядке. – loganfsmyth

+0

Я имею в виду, что он ищет меня, как будет скомпилирован в: 'var отложен; deferred = Q.defer(); FS.readFile ("foo.txt", "UTF-8", функция (ошибка, текст) { , если (ошибка) { deferred.reject (новая ошибка (ошибка));} еще { отложено. разрешение (текст); } }); возвращение; return deferred.promise; ' Так как два возврата после функции – static

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 

любой из этих форм будет работать, но на практике я не вижу, это обычно

+0

Спасибо! это действительно немного втянуто, чтобы столкнуться с такой ситуацией с заявлением о возврате – static

+0

Это не знакомо, но со временем это станет знакомым и, вероятно, вас не потревожит. Я никогда не слышал, чтобы опытные кофейни писали это как хлопотное. –

+0

Потому что это не хлопотно. Внутренние возвраты не имеют запрета на внешнюю функцию. Игнорируй их. – meagar

0

я всегда делаю это так:

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, если вы предпочитаете это).

Я не уверен, что мне нравится нецензурная вставка CodeScript return; можно утверждать, что «явный лучше, чем неявный». Кроме того, можно утверждать, что первый return не должен быть return, а другим ключевым словом, например, stop или finish или somesuch.

как несвязанный sidenote, я не заметил никакого заметного преимущества при использовании обещаний. напротив, я нашел их довольно навязчивыми в своем коде, что с теми deferred и другими понятиями, которые ставятся поверх асинхронного программирования.