2013-03-18 14 views
12

Io sono l'attuazione di una funzione che ha differito valore da restituire e all'interno della funzione ho molti nidificati espressioni condizionali:Come evitare un "ritorno" implicito nel coffeescript in espressioni condizionali?

esempio:

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 

che oltre sarà compilato in:

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; 

Ho bisogno solo dell'ultimo ritorno, ma non dei ritorni if ​​/ else (cioè -> ritorno < - nel codice compilato)

Come posso evitare un simile comportamento (ritorni impliciti laddove non sono necessari) del compilatore coffeescript?

+2

Questo non è il problema che pensi sia. I ritorni in questione stanno tornando dalla funzione di callback interna. Questo è un comportamento desiderabile e non interferisce in alcun modo con il "ritorno" della funzione esterna. – meagar

risposta

12

Coffeescript restituisce automaticamente il risultato delle ultime espressioni, quindi se non si desidera che restituisca i risultati di if, è necessario aggiungere altre espressioni. In questo caso, è sufficiente aggiungere return.

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

Inoltre, error è già un oggetto Error, così puoi semplicemente rifiutarlo direttamente.

deferred.reject(error) 
+0

Grazie!Funziona, ma mi sembra come se fosse compilato in "if/else expression following by return();" e di tutti gli altri codici – static

+0

@static Yep, e questo è assolutamente soddisfacente. – loganfsmyth

+0

Voglio dire, mi sembra come sarà compilato in: 'var differito; posticipato = Q.defer(); FS.readFile ("foo.txt", "utf-8", la funzione (errore, testo) { se (errore) { deferred.reject (nuovo errore (errore));} else { differita. risoluzione (testo); } }); ritorno; return deferred.promise; ' Quindi, come due resi dopo una funzione – static

2

Non è possibile, esattamente. Puoi ignorarli quando non sono necessari (che è la cosa più comune da fare) o fornire un'alternativa esplicita aggiungendo un'istruzione aggiuntiva alla fine della funzione. Penso che provare a farlo sempre nella tua base di codice sta combattendo una guerra contro la lingua che non puoi vincere, quindi la mia raccomandazione personale è solo accettare il ritorno implicito di Mr. Ashkenas e andare avanti a modo tuo.

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 

una di tali forme funzionerà, ma in pratica non vedo questi comunemente

+0

Grazie! è davvero un po 'faticoso imbattersi in una situazione del genere con una dichiarazione di ritorno – static

+0

Non è familiare, ma con il tempo diventerà familiare e probabilmente non ti infastidirà. Non ho mai sentito i coffeescripters esperti menzionarlo come problematico. –

+0

Perché non è fastidioso. I ritorni interiori non hanno nulla a che vedere con la funzione esterna. Ignorali. – meagar

0

lo faccio sempre così:

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

la prima return è lì per interrompere l'esecuzione , per non restituire un valore.

si ottiene ancora un ulteriore (e privo di significato) return nel JS dall'ultima riga del callback; per evitare quello, inserire un ulteriore return null (o semplicemente return se si preferisce).

non sono sicuro che mi piaccia l'inserimento implicito return di CoffeeScript; si potrebbe affermare che "esplicito è meglio di implicito". inoltre, si potrebbe sostenere che il primo return non dovrebbe essere un return ma un'altra parola chiave, ad esempio, stop o finish o somesuch.

come sidenote non correlato, non ho notato alcun vantaggio notevole quando si utilizzano le promesse. al contrario, li ho trovati abbastanza intrusivi nel mio codice, che cosa con quegli deferred s e altri concetti che sono messi al di sopra della programmazione asincrona.

Problemi correlati