2013-07-07 27 views
25

C'è un modo per concatenare Promises insieme in Coffeescript. Ad esempio, si consideri il seguente codice JavaScript,Promesse concatenate in coffeescript

return $.getJSON('/api/post.json') 
    .then(function(response) { 
    // do something 
    }) 
    .then(function(response) { 
    // do something 
    }) 
    .then(null, function(err) { 
    // do something 
    }); 

Ciascuna then's è opzionale, e la finale then deve essere restituito dalla funzione. Attualmente sto scrivendo questo nel CoffeeScript come,

promise = $.getJSON('/api/post.json') 
promise = promise.then (response) -> 
    // do something 

promise = promise.then (response) -> 
    // do something 

promise = promise.then null, (err) -> 
    // do something 

return promise 

C'è un modo migliore per fare questo? Grazie.

+0

Si potrebbe anche dare un'occhiata a IcedCoffeeScript. Funziona in modo leggermente diverso, ma funziona abbastanza bene. –

risposta

40

Ezekiel mostra la direzione corretta, ma non ha bisogno delle parentesi attorno alle funzioni. Basta fare:

$.getJSON '/api/post.json' # As of CoffeeScript 1.7, you don't need the parentheses here either. 
.then (response) -> 
    # do something 
    response # if you would not return anything, promise would be fulfilled with undefined 
.then (response) -> 
    # do something 
    undefined # necessary to prevent empty function body 
.then null, (err) -> 
    # handle error 

Penso che sia sorprendentemente pulito. L'unica cosa che è relativamente disordinata è quando è necessario aggiungere contemporaneamente i gestori respinti e onFulfilled.

Nota: l'ultima volta che ho controllato, questo non funzionava in CoffeeScript Redux, ma era qualche mese fa.

Nota 2: è necessario che almeno una riga del codice effettivo (ovvero non solo un commento) in ciascun corpo di funzione funzioni correttamente. Tipicamente, lo farai, quindi non è un grosso problema.

+0

Grazie. Funziona nel compilatore Coffeescript. –

+0

Downvoted perché non viene compilato in CoffeeScript 1.4.0 o 1.6.3 (più recente). Sono richieste le parentesi come mostrato nella mia risposta. –

+4

@EzekielVictor: Grazie per essere vigile. Ho appena esaminato il problema, e il problema sembra essere che la seconda parte della catena mancava di un corpo funzione. Il commento rientrato apparentemente non è abbastanza. Ho aggiunto un esplicito "indefinito" alla fine in modo che compili. Non ho mai avuto questo problema perché non ho mai avuto corpi funzione non vuoti in questi luoghi. –

4

Questo è probabilmente il migliore che farete:

$.getJSON('/api/post.json') 
    .then((response) -> 
     # do something 
    ).then((response) -> 
     # do something 
    ).then null, (err) -> 
     # do something 

Nota le parentesi che circondano i then() argomenti. Niente di sconvolgente, ma spero che questo aiuti.

+0

Grazie. Perdendo la parentesi, come suggerisce @Meryn Stol, rende un po 'meglio. –

+3

Perdere le parentesi? Suppongo che intendi perderli. Il pensiero di perdere parentesi sul mondo è davvero spaventoso. –

12

Questo è il mio modo preferito di scrivere le promesse, con un po 'indentazione maggiore

doSomething =() -> new RSVP.Promise (resolve, reject) -> 
    if 1 is 1 
    resolve 'Success' 
    else 
    reject 'Error' 

doSomething() 
.then (res) -> 
     console.log 'Step 1 Success Handler' 

    , (err) -> 
     console.log 'Step 1 Error Handler' 

.then (res) -> 
     console.log 'Step 2 Success Handler' 

.then (res) -> 
     console.log 'Step 3 Success Handler' 

    , (err) -> 
     console.log 'Step 3 Error Handler' 

che compila a:

var doSomething; 

doSomething = function() { 
    return new RSVP.Promise(function(resolve, reject) { 
    if (1 === 1) { 
     return resolve('Success'); 
    } else { 
     return reject('Error'); 
    } 
    }); 
}; 

doSomething().then(function(res) { 
    return console.log('Step 1 Success Handler'); 
}, function(err) { 
    return console.log('Step 1 Error Handler'); 
}).then(function(res) { 
    return console.log('Step 2 Success Handler'); 
}).then(function(res) { 
    return console.log('Step 3 Success Handler'); 
}, function(err) { 
    return console.log('Step 3 Error Handler'); 
}); 

Ci sono alcuni casi in cui questo funziona davvero bene anche:

step1Success = (res) -> console.log 'Step 1 Success Handler' 
step1Error = (err) -> console.log 'Step 1 Error Handler' 

step2Success = (res) -> console.log 'Step 2 Success Handler' 

step3Success = (res) -> console.log 'Step 3 Success Handler' 
step3Error = (err) -> console.log 'Step 3 Error Handler' 

doSomething() 
    .then(step1Success, step1Error) 
    .then(step2Success) 
    .then(step3Success, step3Error) 

Testato su coffee-script v1.6.3

+0

Funziona bene, e l'unica cosa che mi ha bloccato per un po 'è assicurarmi che non ci siano spazi nel codice. Questo è probabilmente comune per chi è nuovo al coffeescript, ma non ho potuto ottenere un codice come quello sopra per compilare fino a quando mi sono reso conto che avevo un singolo spazio nel set di schede. –