Как всегда запускать некоторый код, когда обещание выполняется в Angular.js

В моем приложении Angular.js я запускаю некоторую асинхронную операцию. Перед запуском я охватываю приложение модальным div, а затем, как только операция завершена, мне нужно удалить div, была ли операция успешной или нет.

В настоящее время у меня есть это:

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

Он работает хорошо, однако я бы предпочел иметь что-то более чистое, как этот псевдокод:

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

Я предполагаю, что это довольно распространенная проблема, поэтому я думал, что это можно сделать, но ничего не может найти в документе. Любая идея, если это можно сделать?

Ответ 1

Эта функция была реализована в this pull request и теперь является частью AngularJS. Первоначально он назывался "всегда", а затем переименован в finally, поэтому код должен выглядеть следующим образом:

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

Обратите внимание, что поскольку finally является зарезервированным ключевым словом, может потребоваться сделать его строкой, чтобы она не ломалась в некоторых браузерах (например, в браузере IE и Android):

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

Ответ 2

Я использую Umbraco версии 7.3.5 с помощью EndularJS версии 1.1.5 и нашел эту тему. Когда я выполнил одобренный ответ, я получил сообщение об ошибке:

xxx (...), затем (...). наконец, не является функцией

Однако работа была always. Если кто-либо другой, использующий старую версию AngularJS, находит этот поток и не может использовать finally, используйте этот код вместо

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

Ответ 3

Я бы использовал ngView для рендеринга содержимого страницы и инициировал удаление модальности события $viewContentLoaded. См. http://docs.angularjs.org/api/ng.directive:ngView для этого события и http://docs.angularjs.org/api/ng. $rootScope.Scope для прослушивателя событий $on.

Ответ 4

Для тех, кто не использует angularJS, и если вы в порядке с улавливанием ошибки (не уверен, что если .finally() сделает это), вы можете использовать .catch(). then(), чтобы избежать дублирования кода.

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

Ловушка() может оказаться полезной в любом случае для ведения журнала или другой очистки. https://jsfiddle.net/pointzerotwo/k4rb41a7/