Angular2服务发射器订阅失败

时间:2016-11-08 08:31:33

标签: angular angular2-services

参考Global Events in Angular 2我正在尝试实施购物车服务,该服务会在将新商品添加到购物车时发出活动。我在另一个名为navbar的组件(不是购物车的孩子)中订阅了这个服务活动,在那里我展示了我的购物车数量等。

我的购物车服务:

export class CartService {
    public itemAdded$: EventEmitter<any>;
    ...

    constructor(private http: Http){

        this.itemAdded$ = new EventEmitter();
        this.cart=[];
    }

    addToCart(id: any): any {

        this.itemAdded$.emit(id);

        return this.http.get(  this.myUrl + 'add' + '/' + id + '/', { withCredentials:true})
        .toPromise()
        .then(response => response.json())

    }
  ...
  ...
} 

我的导航栏组件:

@Component({
directives:[ROUTER_DIRECTIVES, Cart],
providers:[CartService],

})
export class Navbar implements OnInit{

    ...
    totalCost: any;
    cartItemCount : any;
    addedItem: any;

    constructor(private cartService: CartService){

        this.cartService.itemAdded$.subscribe( (id: any) => {
            alert(id);
            this.onItemAdded(id);
            this.fetchCartElements();
        });
    }

     private onItemAdded(item: any): void {
        // do something with added item
        this.addedItem = item;
    }
...
...
}

但是,每当我添加项目时,导航栏中都不会发生任何事情,即alert(id)onItemAdded()不会自动调用,以便cartItemCount等可以自动更新。

出了什么问题?

3 个答案:

答案 0 :(得分:1)

您应该仅将add(int, Vertex<Integer>)用于EventEmitter

对于您的场景,完全符合@Output() ..

创建Observable并致电Subject,它类似于next()

emit()

订阅部分应该没问题。

答案 1 :(得分:1)

我认为你的错误是一个概念错误。

正如@mxii所说,你的情况完全适合Observable行为,你不应该使用promise和事件发射器(在你的项目实际添加到服务器端之前调用)。

承诺解决方案:

如果你想用承诺修复你的问题,我认为解决方案是在你得到答案后触发事件:

    return this.http.get(  this.myUrl + 'add' + '/' + id + '/', { withCredentials:true})
    .toPromise()
    .then(response => {
                       this.cart.push(response.json());
                       this.itemAdded$.emit(id);
                       });

然后在您的顶级模块(通常是AppModule)中提供它,以确保您的应用程序中只有一个实例。

具有Observable的解决方案:

addToCart(id: any): Observable<any> {//Don't you have an item interface to type the object you get?
        return this.http.get(  this.myUrl + 'add' + '/' + id + '/', { withCredentials:true})
        .map(res => res.json());
    }

然后在NavBar

@Component({
directives:[ROUTER_DIRECTIVES, Cart]
//Note that I removed CartService, as I said you HAVE to provide it on the AppModule, else you'll have different instances accross your application and it seems like it's not what you want.
})
export class Navbar implements OnInit{

    ...
    totalCost: any;
    cartItemCount : any;
    addedItem: any;

    constructor(private cartService: CartService){
    }

     private onItemAdded(item: any): void {
        // do something with added item
        this.addedItem = item;
    }

    public addItemToCart(id:number):void{ 
        //I guess you're adding item from a button click, the button should call this method, passing the id of the item as parameter.
        this.cartService.addToCart(id).subscribe(this.onItemAdded);
    }
...
...
}

答案 2 :(得分:0)

服务是每个提供商的单身您正在向导航栏注入CartService的不同实例,并且正在调用addToCart函数。

我希望应用程序的每个页面都显示Navbar,因此以下是CartService全局单例的方法。

@NgModule({
  declarations: [
  ],
  imports: [
  ],
  providers: [CartService], //<--- added here
  bootstrap: [AppComponent]
})
export class AppModule { }

从模块和组件中删除任何其他providers: [CartService](如果您没有缩进以创建其他实例)