最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mat-table performance issues - once the table has loaded, it freezes the page - Stack Overflow

programmeradmin2浏览0评论

I have a mat-table that has over 150 rows, which doesn't seem like much but it pletely freezes the page (especially if I have the developer console open).

To set the table data I use an input getter and setter (the reason being that it then allows me to make changes in the parent ponent and the child ponent will listen.)

@Input()
get data() {
    return this.dataSource;
}
set data(tableData: any) {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    this.dataSource.data = tableData;
    // moment dates cant be sorted by mat-table: this is their 
    // remendation to convert it to timestamp to be sorted 
    // (still displays as moment date tho :D)
    this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
            case 'momentDueDate': return new Date(item.momentDueDate);
            default: return item[property];
        }
    };
}

The data itself loads relatively quick, however, as soon as I click anything on the page, the page freezes. This even includes trying to change page using mat-pagination on the table.

In my parent ponent, my data is created by an observable using bineLAtest like so:

thisbinedPaymentsAndfilters$ = bineLatest(
    [thisbinedPaymentDetails$,
        this.dateFilter$,
        this.dateToFrom.asObservable(),
        this.typeFilter$,
        this.sortFilter$, 
        this.isAdmin$]).pipe(
            tap(([payments, dateFilter, dateToFrom, type, sort, isAdmin]) => {
        this._router.navigate(['.'], {
            queryParams: {
                date: dateFilter,
                dateFrom: dateToFrom.date_from,
                dateTo: dateToFrom.date_to,
                type: type, 
                order: sort
            },
            relativeTo: this._route,
            replaceUrl: true
        });
    }),
    map(([payments, dateFilter, dateToFrom, type, sort, isAdmin]) => {
        let bined = this.sortPayments(sort, payments);
        if (dateFilter !== 'all') {
            bined = this.filterByDate(payments, dateFilter, dateToFrom);
        }
        if (type !== 'all') {
            bined = bined.filter(
                (payment: any) => payment.paymentType === type);
        }
        this.paymentTitle = this.getViewValue(this.paymentTypeFilter, type);
        this.dateTitle = this.getViewValue(this.dateFilterType, dateFilter);
        return {
            bined,
            isAdmin
        };
    })
);

I also get the following chrome violations whilst in this ponent:

Other things I have tried:

So I have looked at a few similar things online, and people have remended loading the data after the pagination etc (which you can see above I have). Others have also remended using AfterViewInit, I have also tried this, but it still makes no difference. As a way of testing whether there was something else erroring in my code, I have also limited my firestore query to only return 5 items. Once I have done this, it works absolutely fine, which tells me the issue is definitely with the amount of data I am trying to display.

Any remendations on improving this performance as currently, its unusable for production.

EDIT - The issue only really seems to happen when the chrome console is open

I have a mat-table that has over 150 rows, which doesn't seem like much but it pletely freezes the page (especially if I have the developer console open).

To set the table data I use an input getter and setter (the reason being that it then allows me to make changes in the parent ponent and the child ponent will listen.)

@Input()
get data() {
    return this.dataSource;
}
set data(tableData: any) {
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    this.dataSource.data = tableData;
    // moment dates cant be sorted by mat-table: this is their 
    // remendation to convert it to timestamp to be sorted 
    // (still displays as moment date tho :D)
    this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
            case 'momentDueDate': return new Date(item.momentDueDate);
            default: return item[property];
        }
    };
}

The data itself loads relatively quick, however, as soon as I click anything on the page, the page freezes. This even includes trying to change page using mat-pagination on the table.

In my parent ponent, my data is created by an observable using bineLAtest like so:

this.binedPaymentsAndfilters$ = bineLatest(
    [this.binedPaymentDetails$,
        this.dateFilter$,
        this.dateToFrom.asObservable(),
        this.typeFilter$,
        this.sortFilter$, 
        this.isAdmin$]).pipe(
            tap(([payments, dateFilter, dateToFrom, type, sort, isAdmin]) => {
        this._router.navigate(['.'], {
            queryParams: {
                date: dateFilter,
                dateFrom: dateToFrom.date_from,
                dateTo: dateToFrom.date_to,
                type: type, 
                order: sort
            },
            relativeTo: this._route,
            replaceUrl: true
        });
    }),
    map(([payments, dateFilter, dateToFrom, type, sort, isAdmin]) => {
        let bined = this.sortPayments(sort, payments);
        if (dateFilter !== 'all') {
            bined = this.filterByDate(payments, dateFilter, dateToFrom);
        }
        if (type !== 'all') {
            bined = bined.filter(
                (payment: any) => payment.paymentType === type);
        }
        this.paymentTitle = this.getViewValue(this.paymentTypeFilter, type);
        this.dateTitle = this.getViewValue(this.dateFilterType, dateFilter);
        return {
            bined,
            isAdmin
        };
    })
);

I also get the following chrome violations whilst in this ponent:

Other things I have tried:

So I have looked at a few similar things online, and people have remended loading the data after the pagination etc (which you can see above I have). Others have also remended using AfterViewInit, I have also tried this, but it still makes no difference. As a way of testing whether there was something else erroring in my code, I have also limited my firestore query to only return 5 items. Once I have done this, it works absolutely fine, which tells me the issue is definitely with the amount of data I am trying to display.

Any remendations on improving this performance as currently, its unusable for production.

EDIT - The issue only really seems to happen when the chrome console is open

Share Improve this question edited May 12, 2020 at 10:24 Jm3s asked May 12, 2020 at 10:06 Jm3sJm3s 6172 gold badges13 silver badges26 bronze badges 2
  • Most likely there's too much going on in Combined payments function. Try to reduce work into smaller async parts yeilding small but continuous results. You will be able to see areas to improve. – JWP Commented May 12, 2020 at 10:39
  • @JohnPeters Could you expand on that please? Try to reduce work into smaller async parts yeilding small but continuous results – Jm3s Commented May 12, 2020 at 10:43
Add a ment  | 

3 Answers 3

Reset to default 3

Complementing the answer of satanTime, if the bineLatest persists to be spammy even if distinctUntilChanged, you can use the operator debounceTime to force some milliseconds of silence and then get the last result.

Another angular list optimization is to use trackBy.

In this case I would say that too many emits are happening in bineLatest. Perhaps with the same data in case if its filter wasn't changed.

every emit can cause changes of pointers even data is the same and it can cause a new render of the table.

I would add distinctUntilChanged as the first pipe operator to ensure that we really need to emit new value.

It's the implementation with JSON.encode.

.pipe(
   distinctUntilChanged((prev, curr) => JSON.encode(prev) !== JSON.encode(curr))
   ...
)

Then regardless of emits with the same values your pipe won't react until there's a real change.

For what it's worth - I ran into the same symptoms and it turned out that Chrome had an update pending in the background. So, if you also experience "The issue only really seems to happen when the chrome console is open" -- try to reboot Chrome to let the update plete. It worked for me.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论