2016-08-17 4 views
0

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

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

ответ

0

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

//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 должен выполнить это преобразование, но где это подходящее место для его определения? – snusnu

+0

Вы можете предоставить каждому абоненту свой собственный картограф во время фазы регистрации. –

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