2015-08-17 2 views
3

Есть приложение, которое позволяет пользователям создавать или присоединяться к комнатам. Таким образом, есть RoomsListController, который отображает номера, RoomDetailsController, который показывает содержимое и элементы управления для деятельности внутри определенного помещения. И причины, RoomService, которая обеспечивает метод getRooms() (async).Два контроллера в зависимости от одних и тех же данных возвращаются асинхронно

Теперь, каким будет Угловой способ заставить два контроллера ждать тех же данных, возвращаемых RoomService.getRooms()?

Детали:

  • Существует аутентификации в приложение и список номеров зависит от USERID. Поэтому вызов RoomService.getRooms() при запуске приложения не является опцией
  • RoomDetailsController не всегда запрашивает список номеров. Всякий раз, когда комната, предоставляемая через $stateParams, существует и активна, она просто отображается. Если нет, существует некоторая логика, которая направляет пользователя в другую комнату (здесь требуется список комнат) или отображает сообщение о том, что номера не доступны, и, возможно, пришло время его создать.
  • Предположим, что getRooms() - это тяжелая операция для сервера, и не желательно получать его дважды, когда одни и те же данные на клиенте могут быть повторно использованы.
  • Это желательно иметь логику, которая не зависит тот, который функция управления выполняется первый, так как это может повлиять на обновление макета в шаблоне
+1

может использовать решительность в родительском состоянии маршрутизации, чтобы сделать запрос и сохранять результаты в службе. Контроллеры не срабатывают до тех пор, пока не будут решены. – charlietfl

ответ

2

Посмотрите на route resolve promises.

Вы вызываете метод асинхронной перед тем маршрут решает:

// in your config 
$routeProvider.when('/your-route', { 
    resolve: { 
    roomData: function(RoomService) { 
     return RoomService.getRooms(); 
    } 
    } 
} 

// RoomsListController 
function(roomData) { 
    // do something with roomData 
} 

// RoomDetailsController 
function(roomData) { 
    // do something with roomData 
} 

Таким образом, насколько контроллеры обеспокоены, что данные там уже до маршрута даже нагрузок.

Вы затронули одну из ключевых проблем - это приложения, т. Е. Создание единого источника правды для данных, которые составлены таким образом, что приложение может его использовать.

Существует много шаблонов для решения этого вопроса, но я бы рекомендовал взглянуть на обещание по маршруту в качестве отправной точки и разветвиться оттуда. Это может стать очень сложным.

+0

Отлично, это именно то, что мне не хватало! Огромное спасибо! –

1

Другим подходом может быть изменение функции RoomService.getRooms() в вашей службе для объявления и сохранения локального обещания при первом вызове функции, пока вы ожидаете результатов с сервера. Если функция снова вызвана, вы сразу же вернете одно и то же обещание. После того, как результаты будут возвращены с сервера, вы можете решить сохраненное обещание и очистить его, поэтому в следующий раз, когда он будет вызван, будет сделан новый запрос.

Конечно, здесь есть много возможностей для настройки. Если вы знаете, что данные с сервера никогда не будут меняться, например, вам вообще не нужно обещать обещание. Просто возвращайте его каждый раз, когда вас спрашивают.

Вот пример реализации:

var app = angular.module('plunker', []); 
 

 
app.controller('MainCtrl', function($scope, RoomService) { 
 
    $scope.name = 'World'; 
 

 
    $scope.fetchingStatus = function() { 
 
    return RoomService.serverRequests ? 'Fetching... Server Requests: ' + RoomService.serverRequests : ''; 
 
    }; 
 

 
    $scope.getRooms = function() { 
 
    console.log('asking for rooms') 
 
    RoomService.getRooms().then(function(rooms) { 
 
     console.log('rooms returned: ', rooms); 
 
     $scope.rooms = rooms; 
 
    }); 
 
    }; 
 
}); 
 

 
function RoomService($q, $timeout) { 
 
    this.$q = $q; 
 
    this.$timeout = $timeout; 
 
    this.getRoomsPromise = null; 
 
    this.serverRequests = 0; 
 
} 
 

 
RoomService.prototype.getRooms = function() { 
 
    if (!this.getRoomsPromise) { 
 
    this.getRoomsPromise = this.$q.defer(); 
 
    this.getRoomsFromServer(); 
 
    } 
 
    return this.getRoomsPromise.promise; 
 
}; 
 

 
RoomService.prototype.getRoomsFromServer = function() { 
 
    var rooms = []; 
 
    for (var i = 1; i <= 10; i++) { 
 
    rooms.push({ 
 
     id: i, 
 
     name: 'Room ' + i 
 
    }); 
 
    } 
 
    console.log('fetching data from server...'); 
 
    this.serverRequests++; 
 
    this.$timeout(function() { 
 
    this.serverRequests--; 
 
    this.getRoomsPromise.resolve(rooms); 
 
    this.getRoomsPromise = null; 
 
    console.log('got data from server...') 
 
    }.bind(this), 1500); 
 
} 
 

 
app.service('RoomService', RoomService);
.fetching { 
 
    background-color: red; 
 
    color: white; 
 
    padding: 2px 10px; 
 
    display: inline-block; 
 
    margin-left: 50px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script> 
 
<div ng-app="plunker" ng-controller="MainCtrl"> 
 
    <p> 
 
    <button ng-click="getRooms()">Get Rooms</button> 
 
    <span class="fetching" ng-show="fetchingStatus()">{{fetchingStatus()}}</span> 
 
    </p> 
 
    <ul> 
 
    <li ng-repeat="room in rooms track by room.id">{{room.name}}</li> 
 
    </ul> 
 
</div>

+0

Спасибо за подробный фрагмент! –

Смежные вопросы