angularjs меняет rootscope после обещания в контроллере

Я пытаюсь изменить некоторые переменные $rootscope внутри контроллера после получения обещание службы.

Переменные $rootscope используются для установки атрибута заголовка html-страницы и т. д.

Ниже приведен код, который у меня есть. Я создал функцию changeRootPageNotFound() для изменения переменных $rootscope. Не работает, если вызывается в функции promise.then.

app.controller('mainController', ['$routeParams', '$scope', '$rootScope', 'mainService', function ($routeParams, $scope, $rootScope, mainService) {
    var mainCtrl = this;
    mainCtrl.id = $routeParams.itemId;

    var promise = mainService.getData($routeParams.id);

    promise.then(function (response)
    {
        if (response.data.data) {
            mainCtrl.data = response.data.data;
        } else {
            mainCtrl.data = false;
            changeRootPageNotFound();
        }
    });
    function changeRootPageNotFound() {
        $rootScope.title = "Page Not Found - 404";
        $rootScope.titleSuffix = "";
    }
    // changeRootPageNotFound();  // works here
}]);

Как я могу изменить переменные $rootscope после получения отложенного обещания от службы?


person Holly    schedule 30.12.2016    source источник
comment
Вы пытались запустить $rootScope.$digest() после всех изменений корневой области?   -  person John Maclein    schedule 30.12.2016
comment
@JohnMaclein, спасибо, только что попробовал, но не сработало   -  person Holly    schedule 30.12.2016
comment
Подумайте о том, чтобы разместить здесь любое сообщение об ошибке, с которым вы столкнулись.   -  person John Maclein    schedule 30.12.2016
comment
Я сомневаюсь, что promise.then запускается - обычный бэкэнд выдает ошибку из-за недопустимого идентификатора, и ваш обратный вызов не запускается.   -  person Petr Averyanov    schedule 30.12.2016


Ответы (2)


Добавьте метод .catch:

promise.then(function (response)
{
    //if (response.data.data) {
        mainCtrl.data = response.data.data;
    //} else {
    //    mainCtrl.data = false;
    //    changeRootPageNotFound();
    //}
}).catch(function(errorResponse) {
    console.log(errorResponse.status);
    mainCtrl.data = false;
    changeRootPageNotFound();
    throw errorResponse;
});

Служба $http отклоняет обещание, когда статус выходит за пределы диапазона 200–299.


Для чего нужен throw errorResponse;, можно ли его убрать?

Если throw errorResponse опущено, обработчик отклонения возвращает значение undefined. Это преобразует отклоненное обещание в выполненное обещание, которое разрешается как undefined. Если дальнейшей цепочки нет, то ее можно опустить.

Распространенной причиной проблем является то, что программисты не знают об этом и непреднамеренно преобразуют промисы.


вместо .catch вы можете передать ту же функцию в качестве второго аргумента

Одно из тонких различий между .catch и использованием 2-го аргумента метода .then заключается в том, что ошибки времени выполнения в обработчике успеха .then не будут обнаружены в обработчике отклонения 2-го аргумента.

person georgeawg    schedule 30.12.2016
comment
спасибо, что сработало. Для чего нужен throw errorResponse;, можно ли его убрать? Также это кажется правильным способом сделать это, так как мне не нужно условие if (response.data.data) - person Holly; 30.12.2016
comment
@Holy вместо catch вы можете передать ту же функцию в качестве второго аргумента - person Walfrat; 30.12.2016

Согласно вашему фрагменту, ваш код должен был работать. В моем плункере он работает и после отложенного обещания.

// Code goes here
angular.module('Test',[])
  .service('Service', function($q){
    this.ts = function(){
      var deferred = $q.defer();
      deferred.resolve("hello")
      return deferred.promise;
    }
  })
  .controller('Controller', function(Service, $rootScope){

    Service.ts().then(function(response){
      $rootScope.title="hello";
      changeRootPageNotFound();
    });

    function changeRootPageNotFound() {
        $rootScope.title = "Page Not Found - 404";
        $rootScope.titleSuffix = "";
    }
  });

Вот html

<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.8" src="https://opensource.keycdn.com/angularjs/1.5.8/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="Test">
    <div ng-controller="Controller">

      <h1>{{title}}</h1>

    </div>
  </body>

</html>

Пожалуйста, проверьте этот плункер https://plnkr.co/edit/THXDYrWuTqR8UYSJlerB?p=preview

person John Maclein    schedule 30.12.2016