【问题标题】:Angular 12 getting error while defining BehaviorSubject [duplicate]Angular 12 在定义 BehaviorSubject 时出错 [重复]
【发布时间】:2021-09-04 15:07:53
【问题描述】:

我得到的错误:

Argument of type 'null' is not assignable to parameter of type 'IBasket'.
Argument of type 'null' is not assignable to parameter of type 'IBasketTotal'.

服务代码:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, ReplaySubject } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from 'src/environments/environment';
import { Basket, IBasket, IBasketItem, IBasketTotal } from '../share/models/basket';
import { Product } from '../share/models/product';

@Injectable({
  providedIn: 'root'
})
export class BasketService {

  baseUrl = environment.apiUrl;
  private basketSource = new BehaviorSubject<IBasket>(null);
  basket$ = this.basketSource.asObservable();

  private basketTotalSource = new BehaviorSubject<IBasketTotal>(null);
  basketTotal$ = this.basketTotalSource.asObservable();

  constructor(private http: HttpClient) {

  }

  getBasket(id: string) {
    var x = this.http.get<IBasket>(this.baseUrl + "basket?basketId=" + id)
      .pipe(
        map(
          (basket: IBasket) => this.basketSource.next(basket)
        )
      )
    this.getCalculateBasket();
    return x;
  }

  setBasket(basket: IBasket) {
    return this.http.post<IBasket>(this.baseUrl + "basket", basket).subscribe(
      (response: IBasket) => {
        this.basketSource.next(response);
        this.getCalculateBasket();
      },
      error => {
        console.log(error);
      }
    );
  }

  getCurrentBasketValue() {
    return this.basketSource.value;
  }

  getCalculateBasket() {
    try {
      const basket: IBasket = this.getCurrentBasketValue();
      const shipping = 0;
      const subTotal = basket.items.reduce((a, b) => (b.price * b.qty) + a, 0);
      const total = shipping + subTotal;
      this.basketTotalSource.next({ shipping, subTotal, total });
    } catch (error) {
      console.log(error);
    }
  }

  incrementItemQty(item: IBasketItem) {
    const basket: IBasket = this.getCurrentBasketValue();
    const foundIndex = basket.items.findIndex(x => x.id === item.id);
    basket.items[foundIndex].qty++;
    this.setBasket(basket);
  }

  decrementItemQty(item: IBasketItem) {
    const basket: IBasket = this.getCurrentBasketValue();
    const foundIndex = basket.items.findIndex(x => x.id === item.id);
    if (basket.items[foundIndex].qty > 1) {
      basket.items[foundIndex].qty--;
      this.setBasket(basket);
    }
    else {
      this.removeItemFromBasket(item);
    }
  }

  removeItemFromBasket(item: IBasketItem) {
    const basket: IBasket = this.getCurrentBasketValue();
    if (basket.items.some(x => x.id === item.id)) {
      basket.items = basket.items.filter(x => x.id !== item.id);
      if (basket.items.length > 0) {
        this.setBasket(basket);
      }
      else {
        this.deleteBasket(basket);
      }
    }
  }

  deleteBasket(basket: IBasket) {
    return this.http.delete(this.baseUrl + "basket?basketId=" + basket.id).subscribe(() => {
      this.basketSource.next(null);
      this.basketTotalSource.next(null);
      localStorage.removeItem("basket_id");
    }, error => {
      console.log(error);
    });
  }

  addItemBasket(item: Product, qty: number = 1) {
    const itemToAdd: IBasketItem = this.mapProductItemToBasketItem(item, qty);
    const basket: IBasket = this.getCurrentBasketValue() ?? this.createBasket();
    basket.items = this.addOrUpdateItem(basket.items, itemToAdd, qty);
    this.setBasket(basket);
  }
  private addOrUpdateItem(items: IBasketItem[], itemToAdd: IBasketItem, qty: number): IBasketItem[] {
    console.log(itemToAdd);
    const index = items.findIndex(i => i.id === itemToAdd.id);
    if (index === -1) {
      itemToAdd.qty = qty;
      items.push(itemToAdd);
    }
    else {
      items[index].qty += qty;
    }
    return items;
  }

  private createBasket(): IBasket {
    const basket = new Basket();
    localStorage.setItem("basket_id", basket.id);
    return basket;
  }

  private mapProductItemToBasketItem(item: Product, qty: number): IBasketItem {
    return {
      id: item.id,
      name: item.name,
      price: item.price,
      qty: qty,
      pictureUrl: item.pictureUrl,
      brand: item.productBrand,
      type: item.productType
    };
  }
}

产生错误的代码:

private basketSource = new BehaviorSubject<IBasket>(null);
private basketTotalSource = new BehaviorSubject<IBasketTotal>(null);

【问题讨论】:

    标签: angular


    【解决方案1】:

    BehaviorSubject 需要给定类型(IBasket / IBasketTotal)的初始值。

    如果您不想要初始值,只需使用常规主题即可。

    您也可以像这样定义 BehaviorSubject:

    new BehaviorSubject<IBasket | null>
    

    ...但我不明白您为什么要在代码中的任何位置强制使用“null”。

    您可以认为 BehaviorSubject 与通过“startsWith”管道传输的主题相同:

    subject.pipe(startWith("Your initial object goes here"))
    

    【讨论】:

    • 我试过这样定义,但是
    • 我尝试像这样定义它,但是 const basket: IBasket = this.getCurrentBasketValue();我使用的方法给出以下错误类型'IBasket | null' 不可分配给类型 'IBasket'。类型“null”不能分配给类型“IBasket”。
    • 然后首先检查它是否为空,例如= if (yourObjectThatCouldBeNull) { // 在这里赋值 } 或者让你的 const IBasket | null 也是如此,但同样......您可能不应该在代码中传播“null”值。
    • 如果您希望初始值为 null,只需将您正在更新的变量(使用主题)初始化为您声明它的 null,然后将该变量设为 IBasket |空。
    猜你喜欢
    • 2020-09-07
    • 2022-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2020-03-09
    • 2021-05-24
    • 2015-03-01
    相关资源
    最近更新 更多