2013-03-18 2 views
12

j'applique une fonction qui a reporté la valeur de retour et dans la fonction I ont beaucoup imbriquées expressions conditionnelles:Comment éviter un "retour" implicite dans coffeescript dans les expressions conditionnelles?

par exemple:

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 

qui que seront compilés dans:

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; 

Je n'ai besoin que du dernier retour, mais pas du if/else (-> return < - dans le code compilé)

Comment puis-je éviter un tel comportement (retours implicites là où ils ne sont pas nécessaires) du compilateur coffeescript?

+2

Ce n'est pas le problème que vous croyez. Les retours en question reviennent de la fonction de rappel interne. C'est un comportement souhaitable, et cela n'interfère en aucune façon avec le 'retour 'de votre fonction externe. – meagar

Répondre

12

Coffeescript renvoie automatiquement le résultat des dernières expressions, donc si vous ne voulez pas qu'il renvoie les résultats du if, vous devez ajouter d'autres expressions. Dans ce cas, ajoutez simplement return.

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

En outre, error est déjà un objet Error, vous pouvez simplement le rejeter directement.

deferred.reject(error) 
+0

Merci!Cela fonctionne, mais il me semble qu'il sera compilé dans l'expression "if/else suivi de return();" et que tous les autres codes – static

+0

@static Yep, et c'est tout à fait bien. – loganfsmyth

+0

Je veux dire qu'il me semble que sera compilé en: 'var différé; différée = Q.defer(); FS.readFile ("foo.txt", "utf-8", la fonction (erreur, texte) { if (erreur) { deferred.reject (nouvelle erreur (erreur));} else { différé. résoudre (texte); } }); retour; return deferred.promise; ' Donc, comme deux retours après une fonction – static

2

Vous ne pouvez pas, exactement. Vous pouvez soit les ignorer quand ce n'est pas nécessaire (ce qui est la chose la plus courante à faire) ou fournir une alternative explicite en ajoutant une instruction supplémentaire à la fin de la fonction. Je pense qu'essayer de faire cela tout le temps dans votre base de code est une guerre contre la langue que vous ne pouvez pas gagner, donc ma recommandation personnelle est simplement d'accepter le retour implicite de M. Ashkenas et de continuer votre chemin.

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 

l'une de ces formes fonctionnera, mais dans la pratique, je ne vois pas ces communément

+0

Merci! C'est vraiment un peu bizarre de se retrouver dans une telle situation avec une déclaration de retour – static

+0

Ce n'est pas familier, mais avec le temps cela deviendra familier et ne vous dérangera probablement pas. Je n'ai jamais entendu des cafetiers expérimentés mentionner cela comme gênant. –

+0

Parce que ce n'est pas gênant. Les retours internes n'ont aucune mise à nu sur la fonction extérieure. Ignore les. – meagar

0

je fais toujours comme ça:

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

la première return est là pour arrêter l'exécution , ne pas retourner une valeur.

vous obtenez encore return supplémentaire (et insignifiant) dans votre JS de la dernière ligne du rappel; pour éviter cela, insérez un return null supplémentaire (ou simplement return si vous préférez).

Je ne suis pas sûr que j'aime l'insertion return implicite de CoffeeScript; on pourrait dire que «explicite est meilleur qu'implicite». aussi, il pourrait être soutenu que le premier return ne devrait pas être un return mais un autre mot-clé, comme, par exemple, stop ou finish ou quelque chose.

en tant que sidenote sans rapport, je n'ai pas observé d'avantage notable lors de l'utilisation des promesses. au contraire, je les ai trouvés très intrusifs dans mon code, avec ceux-là deferred et d'autres concepts qui sont mis au-dessus de la programmation asynchrone.

Questions connexes