我的网站需要发布广告。我从AdServer收到的广告。我目前有一个组件来完成这项工作。它的工作原理如下:
ROW_NUMBER
在我目前的Angular v6组件中,我需要单独处理每个标记。这意味着(在此示例中)对AdServer的3个不同请求。
但我们的AdServer也支持1个请求,并且所有adPos都已连接在一起。但要做到这一点,我需要阅读所有组件标签,并为所有这些标签提出1个请求。我怎么能用Angular 2 +做到这一点?
答案 0 :(得分:2)
我认为你必须重写你的代码。每个应用广告是否向AdServer发出请求? 如果是这样,您可以创建一个接收数组并查询AdServer一次的服务(pseucod-pseudo-code):
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;
})
}
并且模板使用此数据并传递数据,而不是id
<app-advertising [data]="adServerData[0]"></app-advertising>
...
<app-advertising [data]="adServerData[1]"></app-advertising>
...
<app-advertising [data]="adServerData[2]"></app-advertising>
请注意,这是某种伪代码,解释了如何仅查询此AdServer服务然后使用数据并传递给您编写的组件的主要思路,将app-advertising
组件转换为一个'哑',只接收数据并呈现它。
答案 1 :(得分:0)
尝试不同方法后我自己的答案。
考虑到组件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);
}
});
}
}
答案 2 :(得分:-1)
将广告放入数组然后循环播放。
这样的事情:
<app-advertising *ngFor="let ad of ads"
[adPos]="ad">
</app-advertising>