Angular 6 - Как обрабатывать все компоненты вместе?Не индивидуально - PullRequest
0 голосов
/ 06 июня 2018

Мой сайт должен публиковать рекламу.Реклама, которую я получаю от AdServer.В настоящее время у меня есть компонент для этой работы.Это работает так:

<div>
  ...
  <app-advertising adPos="x22"></app-advertising>
  ...
  <app-advertising adPos="Top"></app-advertising>
  ...
  <app-advertising adPos="x94"></app-advertising>
  ...
</div>

В моем компоненте Angular v6 в настоящее время Мне нужно обрабатывать каждый тег по отдельности.Это означает (в этом примере) 3 разных запроса к AdServer.

Но наш AdServer также поддерживает 1 запрос со всеми конкатенациями adPos.Но для этого мне нужно прочитать все теги компонентов и сделать всего 1 запрос на все из них.Как я могу сделать это, используя Angular 2 +?

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Я думаю, вам придется переписать свой код.Каждое приложение-реклама делает запрос в AdServer?Если это так, вы можете создать службу, которая получит массив и один раз запросить AdServer (псевдокод псевдокода):

class YourService {

   queryAdserver(arrayOfIds): Observable<Array> {
     // query the AdServerService
   }
}

ваш родительский компонент использует эту службу

adServerData: any/ // I don't know the Type here, so I set any
constructor(yourService: YourService) {}

ngOnInit() {
   this.yourService.queryAdserver(['x22', 'Top', 'x94'])
   .subscribe( data => {
      this.adServerData = data;
   })
}

ишаблон использует эти данные и передает данные вместо идентификатора

<app-advertising [data]="adServerData[0]"></app-advertising>
...
<app-advertising [data]="adServerData[1]"></app-advertising>
...
<app-advertising [data]="adServerData[2]"></app-advertising>

Обратите внимание, что это своего рода псевдокод, объясняющий основную идею о том, как запросить только один раз этот сервис AdServer, а затем использоватьданные и передать компоненту, который вы написали, превращая компонент app-advertising в «тупой», который только получает данные и отображает их.

0 голосов
/ 07 июня 2018

Мой собственный ответ после попытки разных подходов.

  • Учитывая, что компонент advertising.component имеет разные позиции рекламы и используется в разных шаблонах (например, article.component.html, header.component.html,video.component.html и т. Д.).Например:

    <!-- in article component, this one: -->
    <app-advertising adPos="x22" adDisp="mobile"></app-advertising>
    <app-advertising adPos="x23" adDisp="mobile"></app-advertising>
    
    <!-- in video component, this one: -->
    <app-advertising adPos="Position1" adDisp="desktop"></app-advertising>
    <app-advertising adPos="x94" adDisp="desktop"></app-advertising>
    
    <!-- in header component, this one: -->
    <app-advertising adPos="x95" adDisp="desktop"></app-advertising>
    
  • Очевидно, Angular использует одноэлементный шаблон, и все компоненты / шаблоны используют один и тот же экземпляр рекламного сервиса.Итак, в моем advertising.service я создал private listPos: Map<string, AdvertisingComponent> = new Map();, где я добавляю все рекламные позиции.

    import { Injectable } from '@angular/core';
    import {AdItemModel, AdModel} from './ad.model';
    import {HttpClient} from '@angular/common/http';
    import {AdvertisingComponent} from './advertising.component';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AdvertisingService {
    
      /**
       * List of positions(advertising) and component instances.
       * @type {Map<string, AdvertisingComponent>}
       */
      private listPos: Map<string, AdvertisingComponent> = new Map();
    
      /**
       * @constructor
       * @param {HttpClient} http (injectable)
       */
      constructor(private http: HttpClient) { }
    
      /**
       * Add position and component instance in the map.
       * Example of position: x22, x95, Position1, etc.
       * @param {string} adPos
       * @param {AdvertisingComponent} element
       * @return void
       */
      public registerPos(adPos: string, element: AdvertisingComponent): void {
        this.listPos.set(adPos, element);
        console.log('Add: ' + Array.from(this.listPos.keys()));
      }
    
      /**
       * Get ads from AdServer. Jsonp request.
       * @param {number} sleepMs
       * @return void
       */
      public getAds(sleepMs: number): void {
    
        setTimeout(() => { // wait for DOM rendering
    
          /**
           * Check if advertising position exist
           */
          if (this.listPos.size === 0) {
            return;
          }
    
          const url = 'http://your-ad-server-url-here@' + Array.from(this.listPos.keys());
    
          this.http.jsonp<AdModel>(url, '_RM_HTML_CALLBACK_').subscribe((response: AdModel) => {
    
            // process all ads
            this.process(response.Ad);
    
            // clean map
            this.listPos.clear();
    
          });
    
        }, sleepMs);
    
      }
    
      /**
       * Process list of advertising and publish them in their respecive position in the templates.
       * @param {AdItemModel[]} items
       * @return void
       */
      private process(items: AdItemModel[]): void {
    
        items.forEach((value: AdItemModel) => {
    
          /**
           * Get the 'AdvertisingComponent' instance from the Map and print the advertising there.
           * @type {V | undefined}
           */
          const adComponentInst: AdvertisingComponent = this.listPos.get(value.Pos);
          if (adComponentInst !== null) {
            adComponentInst.ad = value.SOMETHING; // the value object depends on your AdServer
          }
    
        });
    
      }
    
    }
    
  • В моем advertising.component единственное, что я делаю, это добавляюПозиция (adPos) параметра тега и экземпляр компонента для службы Map.

    import {Component, Input, OnDestroy, OnInit} from '@angular/core';
    import {AdvertisingService} from './advertising.service';
    
    @Component({
      selector: 'app-advertising',
      templateUrl: './advertising.component.html',
      styleUrls: ['./advertising.component.css']
    })
    export class AdvertisingComponent implements OnInit {
    
      @Input() adPos: string;
      @Input() adDisp: string;
      public ad = '';
    
      /**
       * @constructor
       * @param {AdvertisingService} adService
       */
      constructor(private adService: AdvertisingService) {}
    
      ngOnInit() {
        /**
         * Register the current position and instance in the Advertising Service
         */
        this.adService.registerPos(this.adPos, this);
      }
    
    }
    
  • А в моем AppComponent, когда событие NavigationEnd равноЗахваченный, я вызываю advertising.service, чтобы получить от AdServer ВСЕ позиции вместе (только ОДИН ЗАПРОС) и добавить все результаты в соответствующую позицию экземпляра.

    import {Component} from '@angular/core';
    import {NavigationEnd, Router} from '@angular/router';
    import {AdvertisingService} from './advertising/advertising.service';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    
      title = 'Website Beta';
    
      /**
       * @constructor
       * @param {Router} router
       * @param {AdvertisingService} adService
       */
      constructor(private router: Router, private adService: AdvertisingService) {
    
        /**
         * Detect route changes
         */
        this.router.events.subscribe(event => {
          //  console.log(event.constructor.name);
          if (event instanceof NavigationEnd) {
    
            /**
             * Execute advertising after a few miliseconds
             */
            this.adService.getAds(500);
    
          }
        });
    
      }
    
    }
    
0 голосов
/ 06 июня 2018

Поместите ваши объявления в массив, затем выполните цикл.

Примерно так:

<app-advertising *ngFor="let ad of ads"
[adPos]="ad">
</app-advertising>
...