2013-04-16 16 views
77

Nella mia applicazione Angular.js, sto eseguendo un'operazione asincrona. Prima che inizi copro l'applicazione con un div modale, quindi una volta completata l'operazione, ho bisogno di rimuovere il div, se l'operazione è andata a buon fine o meno.Come eseguire sempre del codice quando una promessa è soddisfatta in Angular.js

Attualmente ho questo:

LoadingOverlay.start(); 
Auth.initialize().then(function() { 
    LoadingOverlay.stop(); 
}, function() { 
    LoadingOverlay.stop(); // Code needs to be duplicated here 
}) 

Funziona bene, ma preferirei avere qualcosa di più pulito come questo pseudo-codice:

LoadingOverlay.start(); 
Auth.initialize().finally(function() { // *pseudo-code* - some function that is always executed on both failure and success. 
    LoadingOverlay.stop(); 
}) 

Penso che sia piuttosto un problema comune, in modo da Stavo pensando che potrebbe essere fatto ma non riesco a trovare nulla nel doc. Qualche idea se si può fare?

+0

Se si può incatenare uno 'then()', allora si può sicuramente incatenare un altro ... '.initialize(). Then (...). Then (...)'. Non c'è "finalmente" in quanto tale; il gestore finale è l'ultimo specificato. –

+2

@ Beetroot-Beetroot, che non funzionerà perché se 'initialize()' fallisce, è comunque necessario dichiarare sia una funzione "success" che una funzione "fail" e un codice duplicato. –

+0

Non funzionerà, o semplicemente poco elegante? –

risposta

148

La funzione è stata implementata in this pull request ed è ora parte di AngularJS. E 'stato inizialmente chiamato "sempre" e successivamente rinominato finally, in modo che il codice dovrebbe essere come segue:

LoadingOverlay.start(); 
Auth.initialize().then(function() { 
    // Success handler 
}, function() { 
    // Error handler 
}).finally(function() { 
    // Always execute this on both error and success 
}); 

Nota che, dal momento finally è una parola chiave riservata, potrebbe essere necessario fare una stringa in modo che non si rompe in alcuni browser (come Internet Explorer e Android browser):

$http.get('/foo')['finally'](doSomething); 
+9

Per chiunque lo trovi da una ricerca sul web, il link nella risposta si riferisce alla funzione 'sempre' ma è stato cambiato in' finally' come si può vedere in questo commit (o nella fonte): https: // github. com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c –

+0

@AustinThompson, grazie per l'informazione, ho aggiornato il post. –

+0

@ this.lau_ l'ultima() deve essere l'ultima chiamata nella catena, oppure posso eseguire una catena più di (poi) s di essa? – Brian

7

sto usando Umbraco versione 7.3.5 back-end con AngularJS la versione 1.1.5 e ho trovato questo thread. Quando ho implementato la risposta approvato ho ottenuto l'errore:

xxx(...).then(...).finally is not a function

Che cosa ha fatto il lavoro però è stato always. Se qualcun altro usando una vecchia versione di AngularJS trova questa discussione e non può usare finally uso di questo codice al posto

LoadingOverlay.start(); 
Auth.initialize().then(function() { 
    // Success handler 
}, function() { 
    // Error handler 
}).always(function() { 
    // Always execute this on both error and success 
}); 
0

Per quelle che non utilizzano angularJS, e se siete ok con la cattura l'errore (non so se. infine() lo farebbe), potreste usare .catch(). then() per evitare il codice duplicato.

Promise.resolve() 
    .catch(() => {}) 
    .then(() => console.log('finally')); 

Il catch() potrebbe risultare utile per la registrazione o altre operazioni di pulizia. https://jsfiddle.net/pointzerotwo/k4rb41a7/