Приложение с несколькими службами данных API

0

Я пытаюсь создать приложение с угловым выражением, в котором есть компоненты, которые регистрируют функцию обратного вызова и "объект запроса данных" с помощью услуги "Угловая". Эта служба в основном отслеживает все объекты запроса данных и какие функции обратного вызова они ссылаются. Затем он выполняет длительный опрос, чтобы сделать асинхронные вызовы 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);

У части, с которой мне сложно понять, как реализовать, является "образ преобразования данных". Насколько я могу судить, действительно есть только два места, где я могу увидеть, где может произойти это преобразование данных:

  1. Внутри компонента
  2. Внутри отдельных служб API

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

Но второй способ также представляет собой еще одну проблему: каждая служба RESTful API должна иметь функции преобразования для каждого типа компонента, который я создал. Это как-то не кажется мне "чистым".

Есть ли другой способ разработки моего приложения для достижения этой цели? Любое понимание было бы оценено.

Теги:

1 ответ

0

Просто предложение: используйте угловую встроенную систему событий.

//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);
    });
  }
  • 0
    Спасибо за чаевые. Я не осознавал, что вы можете использовать $ emit и $ таким образом (или что $ on возвращает функцию отмены регистрации, особенно удобную). Для responseToEventsMapper мой вопрос по-прежнему заключается в том, следует ли определять маппер в службе или в компоненте? Скажем, у меня есть два API, apiA и apiB. Они оба возвращают ответы в совершенно разных форматах, jsonA и jsonB. Но компонент требует, чтобы данные были в другом формате, jsonC. responseToEventsMapper должен выполнить это преобразование, но где подходящее место для него должно быть определено?
  • 0
    Вы можете предоставить каждому подписчику свой собственный картограф на этапе регистрации.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню