Я пытаюсь создать приложение с угловым выражением, в котором есть компоненты, которые регистрируют функцию обратного вызова и "объект запроса данных" с помощью услуги "Угловая". Эта служба в основном отслеживает все объекты запроса данных и какие функции обратного вызова они ссылаются. Затем он выполняет длительный опрос, чтобы сделать асинхронные вызовы API RESTful. Когда все данные поступают, служба решает, какие компоненты нуждаются в том, какие части данных и вызовы в них получаются с результатами вызова API.
Проблема, с которой у меня возникают проблемы, сводя вокруг меня голову, состоит в том, что каждому компоненту может понадобиться преобразование данных в объект JSON, который предписывает конкретный формат. Например, компонент диаграммы может потребовать, чтобы результат данных выглядел в одну сторону, но компонент таблицы, который может потребовать, чтобы результат данных выглядел другим способом.
Чтобы сделать вещи еще более сложными, я хочу создать свою службу передачи данных таким образом, чтобы компонент мог регистрироваться для данных из нескольких различных API RESTful.
Поскольку я довольно новичок в Angular, я хотел получить помощь по некоторым передовым практикам для решения этого типа приложений. То, что я собираюсь сделать, - это "первичная" служба данных, с которой регистрируются мои компоненты. Функция регистрации примет в качестве аргумента функцию обратного вызова и объект запроса данных, который будет в таком формате:
{
"service": "apiService",
"request": {
...
}
}
Тогда для каждого RESTful API будет отдельный Угловой сервис. Эти под-сервисы будут обрабатывать, что делать с объектом запроса данных, и соответствовать указанному выше "сервису". Затем первичная служба данных ставит очередь на запросы к под-сервисам в течение длительного цикла опроса. Поэтому первичная служба данных будет выглядеть примерно так (ПРИМЕЧАНИЕ: я использую ES6):
class DataService {
constructor($q, $interval, $injector) {
this.$q = $q;
this.$interval = $interval;
this.$injector = $injector;
this.subscriptions = [];
this.callbacks = [];
this.poll();
}
poll() {
let reqs = [];
angular.forEach(this.subscriptions, (sub, i) => {
let service = this.$injector.get(sub.service);
let deferred = this.$q.defer();
reqs.push(deferred);
service.get(sub.request).then((result) => {
this.callbacks[i](result);
deferred.resolve(result);
}, (result) => {
deferred.reject(result);
});
});
this.$q.all(reqs).then(() => {
this.$interval(poll, this.pollInterval || 10000);
});
}
register(request, callback) {
this.subscriptions.push(request);
this.callbacks.push(callback);
}
}
angular.module('DataService', []).service('DataService', DataService);
У части, с которой мне сложно понять, как реализовать, является "образ преобразования данных". Насколько я могу судить, действительно есть только два места, где я могу увидеть, где может произойти это преобразование данных:
Первый способ не кажется мне жизнеспособным вариантом, поскольку он нарушает обычную практику, что компоненты должны быть несколько "тупыми". Компонент не должен обрабатывать преобразование данных, возвращаемых API RESTful: он должен просто использовать данные как есть.
Но второй способ также представляет собой еще одну проблему: каждая служба RESTful API должна иметь функции преобразования для каждого типа компонента, который я создал. Это как-то не кажется мне "чистым".
Есть ли другой способ разработки моего приложения для достижения этой цели? Любое понимание было бы оценено.
Просто предложение: используйте угловую встроенную систему событий.
//Constructor
constructor($q, $interval, $injector, $rootScope) {
this.$q = $q;
this.$interval = $interval;
this.$injector = $injector;
this.$rootScope = $rootScope;
this.listeners = [];
//No idea how its written in Angular2 but cleanup the event listeners when this is destroyed
//Example in 1.5.x:
//$scope.$on('$destroy', () => angular.forEach(this.listeners, l => l());
this.poll();
}
//The new register method
register(ev, callback) {
//When cleaning up - iterate over listeners and invoke each destroy function - see constructor
this.listeners.push(this.$rootScope.$on(ev, callback));
}
//The new poll method
poll() {
let reqs = [];
angular.forEach(this.subscriptions, (sub, i) => {
let service = this.$injector.get(sub.service);
let deferred = service.get(sub.request).then((response) => {
//responseToEventsMapper should map and parse response to list of events to fire.
//Lets say the response is an authentication response for login attempt,
//then the triggered events will be 'Auth:stateChange' and 'Auth:login' with
//response.user as data. configure responseToEventsMapper upfront.
let events = this.responseToEventsMapper(response);
angular.forEach(events, event => this.$rootScope.$emit(event.type, event.data));
});
reqs.push(deferred);
});
this.$q.all(reqs).then(() => {
this.$interval(poll, this.pollInterval || 10000);
});
}