Впрысните данные от ngResource в регулятор с разрешением ui-маршрутизатора

В документации angular ui-router указано, что экземпляр контроллера будет создан только после выполнения всех обещаний, включая извлечение данных с удаленного сервера.

У меня есть экземпляр $resource:

angular.module('app')
    .factory('Item', item);

item.$inject = ['$resource'];

function item($resource) {
    return $resource('/items/:id/', {id: '@id'}, {
        update: {method: 'PATCH'}
    });
}

И я определяю состояние, которое принимает идентификатор из url и извлекает данные из REST API:

     $stateProvider.state('item', {
            url: '/item/:itemId',
            templateUrl: '../components/item/item.html',
            controller: 'ItemController',
            resolve: {
                item: function ($stateParams, Item) {
                    return Item.get({id: $stateParams.itemId});
                }
            }
        })

В контроллере я пытаюсь использовать параметр Item, предполагая, что если контроллер работает, то все данные уже извлечены, и я могу свободно использовать его:

angular.module('app')
    .controller('ItemController', ItemController);

ItemController.$inject = ['$scope', 'item', 'Item'];

function ItemController($scope, item, Item) {

        $scope.item = item;
        $scope.similarItems = Item.query({item_type__id: $scope.item.item_type_detail.id});
} 

Но браузер дает мне эту ошибку:

TypeError: не удается прочитать свойство » id » undefined

И указывая на эту точную линию, это означает, что $ scope.пункт.item_type_detail по — прежнему не определен, другими словами-не разрешен.

Но если я оберну свой второй вызов элемента (в контроллере) в тайм-аут$, скажем, 5000ms, это будет работать хорошо, это означает, что проблема не в вызове ajax или неправильной инъекции зависимости, но что контроллер каким-то образом получает экземпляр до разрешения обещания.
Как это можно объяснить и что я могу сделать, чтобы исправить это?

1 ответ

  1. Возврат обещания в функцию resolver:

    $stateProvider.state('item', {
        url: '/item/:itemId',
        templateUrl: '../components/item/item.html',
        controller: 'ItemController',
        resolve: {
            item: function ($stateParams, Item) {
                //return Item.get({id: $stateParams.itemId});
                return Item.get({id: $stateParams.itemId}).$promise;
                //return promise --------------------------^^^^^^^^^
            }
        }
    })
    

    Важно понимать, что вызов $resourceметода объекта немедленно возвращает пустую ссылку. Как только данные возвращаются с сервера, существующая ссылка заполняется фактическими данными.

    Возвращая $promiseсвойство, маршрутизатор будет ожидать данных от сервера.