【问题标题】:Rxjs include deeply nested objects in behaviorsubjectRxjs 在 behaviorsubject 中包含深度嵌套的对象
【发布时间】:2016-08-15 13:12:48
【问题描述】:

我开始在 Rxjs 中使用 BehaviorSubject,但在这方面的经验有限。到目前为止,我能够获取组件中的根级参数,但访问嵌套对象会导致“无法读取未定义的属性 x”。

类:

export class Basket extends X23Object {
    public BasketId: number;
    public UserID: number;
    public User: User;
    public BasketLines: BasketLine[] = [];
}

export class BasketLine extends X23Object {
    public BasketLineId: number;
    public BasketId: number;
    public ProductId: number;
    public Quantity: number;
    public Product: Product;
    public Price: number;
    public Name: string;
}
export class Product extends X23Object {
    public ProductId: number;
    public CategoryId: number;
    public Name: string;
    public Code: string;
    public Price: number;
    public Details: string;
    public Images: Image[];
    public Category: Category;
}

BasketBackendService

GetBasket() {
    return this.authHttp.get(this.apiUrl + 'api/GetBasketByUser?id=' + parseInt(this.decodedJwt['userId']), { headers: contentHeaders });
}

篮子服务

private _lines: BehaviorSubject<BasketLine[]> = new BehaviorSubject([new BasketLine]);
get getLines() {
    return this._lines.asObservable();
}
loadBasket() {
    this.basketBackendService.GetBasket()
        .subscribe(
            response => {
                let lines = <BasketLine[]>response.json().basket.BasketLines;

                this._lines.next(lines);
            },
            error => console.log(error.text())
        );
}

模板(sn-p)

<tr *ngFor="let line of basketService.getLines | async">
    <td><img class="login-logo" src="{{ line.Product.Images[0].ThumbUrl }}" width="100%" /></td>
    <td><a [routerLink]="['Product', { id: line.ProductId }]"> {{ line.Product.Code }} </a></td>
    <td><a [routerLink]="['Product', { id: line.ProductId }]">{{ line.Product.Name }}</a></td>
    <td class="text-right">{{ line.Price | currency:'GBP':true:'.2-2' }}</td>
    <td class="text-center">{{ line.Quantity }}</td>
    <td class="text-right">{{ line.Quantity * line.Price | currency:'GBP':true:'.2-2' }}</td>
    <td><button (click)="DeleteLine(line.BasketLineId)">Remove</button></td>
</tr>

如果我删除深度嵌套对象的引用,我会返回预期的结果。

我正在尝试使用 BehaviorSubject 来更新几个组件,但不确定这是否是最好的解决方案!

【问题讨论】:

    标签: angular rxjs behaviorsubject


    【解决方案1】:

    代码对我来说看起来不错,我猜你所说的“深度嵌套”是指例如line.Product.Code。如果它适用于line.Quantity,那么问题很可能不在BehaviorSubject,而是在您的数据结构中。

    我不知道您的特定用例是什么,但您根本不需要使用 BehaviorSubjectasync 管道。

    对于BasketService,您可以只使用:

    export class BasketService {
        lines: BasketLine[];
    
        // ...
    
        loadBasket() {
            this.basketBackendService.GetBasket().subscribe(
                response => {
                    this.lines = <BasketLine[]>response.json().basket.BasketLines;
                },
                error => console.log(error.text())
            );
        }
    }
    

    然后只渲染它:

    <tr *ngFor="let line of basketService.lines">
        // ...
    </tr>
    

    【讨论】:

    • 这种方法的问题是它不会更新其他组件。我有一个在标题中显示购物篮的组件,它只会更新您刷新页面。我正在寻找一种服务/主题方法来使购物篮数据可观察并在所有相关组件中更新购物篮,而无需刷新页面。
    • 看起来深度嵌套的对象可能显示为未定义,因为变更管理会在对象准备好之前更新组件,但并非总是如此
    • 您不必手动更新任何组件,Angular 的更改检测会为您完成,除非您在组件中摆弄ChangeDetectorRef 的引用,我认为您不是正在做。您可以尝试运行 Application.tick() 方法来强制它运行更改检测,但我怀疑这会对您有所帮助。我认为数据的结构与您期望的不同。尝试使用{{line | json}} 转储它。
    • 另外,不可能只更新部分参考资料而保持那些“深层嵌套”不变。您正在使用对象引用,因此当从 JSON 解码新对象时,它会替换原始引用,Angular 会检测并更新它。
    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 2021-10-02
    • 1970-01-01
    • 2019-09-10
    • 2017-08-27
    • 2018-11-30
    • 2017-04-04
    • 1970-01-01
    相关资源
    最近更新 更多