错误TypeError:无法读取null

时间:2019-10-25 08:18:32

标签: typescript firebase-realtime-database shopping-cart angular8

当我从购物车中删除所有产品时,主页中没有显示任何产品,并且浏览器控制台显示错误 ERROR TypeError:无法读取null的属性'items'

shopping-cart.service.ts

export class ShoppingCartService {

  constructor(private db: AngularFireDatabase) {}

    private create() {
        return this.db.list('/shopping-carts').push({
            dateCreated: new Date().getTime()
        });
    }

    async getCart(): Promise<Observable<ShoppingCart>> {
        let cartId = await this.getOrCreateCartId();
        return this.db
            .object('/shopping-carts/' + cartId)
            .snapshotChanges()
      .pipe(map((x) => new ShoppingCart(x.payload.exportVal().items //ERROR TypeError: Cannot read property 'items' of null
      )));
    }

    private getItem(cartId: string, productId: string) {
        return this.db.object('/shopping-carts/' + cartId + '/items/' + productId);
    }

    private async getOrCreateCartId(): Promise<string> {
        let cartId = localStorage.getItem('cartId');

        if (cartId) return cartId;

        let result = await this.create();
        localStorage.setItem('cartId', result.key);
        return result.key;
    }

    async addToCart(product: Product) {
        this.updateItem(product, 1);
    }

    async clearCart() {
        let cartId = await this.getOrCreateCartId();
        this.db.object('/shopping-carts/' + cartId + '/items').remove();
    }

    async removeFromCart(product: Product) {
        this.updateItem(product, -1);
    }

    private async updateItem(product: Product, change: number) {
        let cartId = await this.getOrCreateCartId();
        let item$ = this.getItem(cartId, product.key);
        item$.snapshotChanges().pipe(take(1)).subscribe((item) => {
            if (item.payload.exists()) {
                let quantity = item.payload.exportVal().quantity + change;
                if (quantity === 0) item$.remove();
                else
                    item$.update({
                        product: product,
                        quantity: quantity
                    });
            } else {
                item$.set({ product: product, quantity: 1 });
            }
        });
    }
}

在models文件夹中 shopping-cart.ts

import { ShoppingCartItem } from './shopping-cart-item';
import { Product } from './product';

export class ShoppingCart {
    items: ShoppingCartItem[] = [];
    constructor(private itemsMap: { [productId: string]: ShoppingCartItem }) {
        this.itemsMap = itemsMap || {};
        for (let productId in itemsMap) {
            let item = itemsMap[productId];
            this.items.push(new ShoppingCartItem(item.product, item.quantity));
        }
    }

    getQuantity(product: Product) {
        let item = this.itemsMap[product.key];
        return item ? item.quantity : 0;
    }

    get totalPrice() {
        let sum = 0;
        for (let productId in this.items) {
            sum += this.items[productId].totalPrice;
        }
        return sum;
    }

    get totalItemsCount() {
        let count = 0;
        for (let productId in this.itemsMap) count += this.itemsMap[productId].quantity;
        return count;
    }
}

shopping-cart-item.ts

import { Product } from './product';

export class ShoppingCartItem {
    key: string;
    title: string;
    imageUrl: string;
    price: number;

    constructor(public product: Product, public quantity: number) {}
    get totalPrice() {
        return this.product.price * this.quantity;
    }
}

shopping-cart.component.ts

export class ShoppingCartComponent implements OnInit {
    cart$: Observable<ShoppingCart>;
    constructor(private shoppingCartService: ShoppingCartService) {}

    async ngOnInit() {
        this.cart$ = await this.shoppingCartService.getCart();
    }
    clearCart() {
        this.shoppingCartService.clearCart();
    }
}

shopping-cart.component.html

<ng-container *ngIf="cart$ | async as cart">

    <table class="table">

        <tbody>
            <tr *ngFor="let item of cart.items">
                <td>
                    <img
                      [src]="item.product.imageUrl"
                      class="thumbnail"
                      alt=""
                    >
                </td>
                <td>{{  item.product.title }}</td>
                <td>
                    ${{item.product.price}} X {{ item.quantity }}
                </td>
                <td>
                    <app-product-quantity
                        [product]="item.product"
                        [shopping-cart]="cart"
                    ></app-product-quantity>
                </td>               
                <td>
                    {{ item.totalPrice | currency: 'USD':true}}
                </td>
            </tr>
        </tbody>
        <tfoot>
            <tr>                
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th>
                    {{ cart.totalPrice | currency:'USD':true}}
                </th>
            </tr>
        </tfoot>
    </table>

    <button
        *ngIf="cart.items.length"
        type="button"
        (click)="clearCart()"
        class="btn btn-light btn-block"
    >
        Clear Shopping Cart
    </button>

</ng-container>

我要从购物车中删除所有产品后,在浏览器的主页上将显示所有产品。

1 个答案:

答案 0 :(得分:0)

async getCart(): Promise<Observable<ShoppingCart>> {
    let cartId = await this.getOrCreateCartId();
    return this.db
        .object('/shopping-carts/' + cartId)
        .valueChanges()
        .pipe(map((x)=> (x) ? new ShoppingCart(( x as any).items): (x as any)
  ));
}