项未在Angular类中推送到数组

时间:2019-03-16 18:32:57

标签: angular typescript rxjs

我做了一个Angular Service,它保留了其他组件可以向其中添加和检索的项目列表。由于某种原因,没有任何内容添加到列表中。它仅在我的服务的add()函数中起作用,但变量不会在其外部被更改。例如,在add()函数末尾,控制台将返回添加的项。但是,当我再次从getItems()函数列表中检查列表时,该列表为空。为什么在推送后list不会在函数之外得到更新?

    export class BasketService {
      private list: Item[] = [];
      constructor() {}

      add(product: Product, units: number): void {
        let item: Item = new Item();
        item.product = product;
        item.units = units;
        this.list.push(item);
        console.log(this.list[(this.list.length - 1)]);
        // Log shows item object
      }
      getItems(): Observable<Item[]> {
        console.log(this.list);
        // Log shows empty array
        return of(this.list);
      }
    }

编辑

getItems()确实有一个订阅者,但是问题似乎并不出在那儿,因为它接收到一个空的Item数组,即控制台在getItems(在basketService中)打印的相同的空列表。

export class BasketComponent implements OnInit {
  items: Item[];

  constructor(private basketService: BasketService) {}

  ngOnInit() {
    this.getItems();
    console.log(this.items.length);
  }
  getItems(): void {
    this.basketService.getItems()
      .subscribe(items => {
        this.items = items; });
  }

2 个答案:

答案 0 :(得分:1)

您的getItems()方法返回一个Observable,其中包含您的项目列表。您需要订阅该Observable才能获得这些物品。

此外,每次修改列表时,您都可以使用BehaviorSubject将列表推入Observable中。

这样,当添加项目时,您的服务使用者将通过可观察对象得到通知。

@Injectable()
export class BasketService {
  private list: Item[] = [];
  private subject = new BehaviorSubject<Item[]>([]);
  private list$ = this.subject.asObservable();

  add(product: Product, units: number): void {
    let item: Item = new Item();
    item.product = product;
    item.units = units;
    this.list.push(item);
    this.subject.next(this.list); // push the modified list to notify observers
  }
  getItems(): Observable<Item[]> {
    return this.list$;
  }
}

像这样使用它:

export class MyComponent implements OnInit {
  constructor(private service: BasketService) { }

  ngOnInit() {
    this.service.getItems().subscribe(items => {
      console.log('list modified', items); // this is executed after each list.push()
    });
  }
}

您还可以将scanSubject一起使用,并摆脱list变量。该列表将由scan运算符通过附加到先前的值来创建:

@Injectable()
export class BasketService {
  private subject = new Subject<Item>();
  private list$ = this.subject.pipe(
    scan((list, item) => [...list, item], [] as Item[]),
  );

  add(product: Product, units: number): void {
    let item: Item = new Item();
    item.product = product;
    item.units = units;
    this.subject.next(item);
  }
  getItems(): Observable<Item[]> {
    return this.list$;
  }
}
  

这里是使用扫描运算符的简短Stackblitz demo

答案 1 :(得分:0)

请确保您的服务使用@Injectable装饰并正确提供,以便使用该服务的所有组件  具有相同的服务实例。