admin管理员组文章数量:1192555
This code works fine for displaying the timer, when i open it after the browser is loaded properly, in other words, if i open my profile section first and wait for the browser to finish loading and then navigate back to the home page, the countdown works fine . But if i reload the page from home page, it keeps on spinning.
`/* eslint-disable @typescript-eslint/no-unused-vars */
import {
Component,
OnInit,
OnDestroy,
ViewChild,
afterNextRender,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { Carousel, CarouselModule } from 'primeng/carousel';
import { ButtonModule } from 'primeng/button';
import { TagModule } from 'primeng/tag';
import { AuctionService } from '../../../services/auction/auction.service';
import { interval, Subscription } from 'rxjs';
interface Auction {
id: number;
auction_end_date: string;
timeRemaining?: string;
[key: string]: any;
}
@Component({
selector: 'app-auctions',
standalone: true,
imports: [
CommonModule,
RouterModule,
CarouselModule,
ButtonModule,
TagModule,
],
templateUrl: './auctionsponent.html',
styleUrl: './auctionsponent.scss',
})
export class AuctionsComponent implements OnInit {
@ViewChild('carousel') carousel!: Carousel;
@ViewChild('carouselFuture') carouselFuture!: Carousel;
liveAuctions: Auction[] = [];
futureAuctions: Auction[] = [];
groupedFutureAuctions: any[][] = [];
responsiveOptions: any[] | undefined;
private countdownSubscription: Subscription | null = null;
constructor(private auctionService: AuctionService) {}
ngOnInit(): void {
this.responsiveOptions = [
{
breakpoint: '1199px',
numVisible: 1,
numScroll: 1,
},
{
breakpoint: '991px',
numVisible: 2,
numScroll: 1,
},
{
breakpoint: '767px',
numVisible: 1,
numScroll: 1,
},
];
this.fetchLiveAuctions();
this.fetchFutureAuctions();
}
startCountdown(): void {
this.countdownSubscription = interval(1000).subscribe(() => {
this.liveAuctions = this.liveAuctions.map((auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(auction.auction_end_date),
}));
this.futureAuctions = this.futureAuctions.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(auction.auction_end_date),
}));
this.groupFutureAuctions();
});
}
groupFutureAuctions(): void {
this.groupedFutureAuctions = [];
for (let i = 0; i < this.futureAuctions.length; i += 4) {
this.groupedFutureAuctions.push(this.futureAuctions.slice(i, i + 4));
}
}
fetchLiveAuctions(): void {
this.auctionService
.getLiveAuctions()
.then((result: any) => {
// console.log('Result in fetch live auctions', result.data);
if (result?.data) {
this.liveAuctions = result.data.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(
auction.auction_end_date
),
}));
}
this.startCountdown();
})
.catch((error) => {
console.error('Error fetching live auctions:', error);
});
}
fetchFutureAuctions(): void {
this.auctionService
.getFutureAuctions()
.then((result: any) => {
console.log('Result in fetch future auctions', result.data);
if (result?.data) {
this.futureAuctions = result.data.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(
auction.auction_end_date
),
}));
}
this.groupFutureAuctions();
})
.catch((error) => {
console.error('Error fetching live auctions:', error);
});
}
calculateTimeRemaining(endDate: string): string {
if (!endDate) return 'Invalid date';
const end = new Date(endDate).getTime();
if (isNaN(end)) return 'Invalid date';
const now = Date.now();
const diff = end - now;
if (diff <= 0) return 'Auction ended';
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return `${days}D ${hours}H ${minutes}M ${seconds}S`;
}
prevLive(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carousel?.navBackward(event);
}
}
nextLive(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carousel?.navForward(event);
}
}
prevFuture(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carouselFuture?.navBackward(event);
}
}
nextFuture(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carouselFuture?.navForward(event);
}
}
getSeverity(status: string) {
switch (status) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warning';
case 'OUTOFSTOCK':
return 'danger';
default:
return 'info';
}
}
trackByAuctionId(index: number, auction: any): number {
return auction.id;
}
}
`
This code works fine for displaying the timer, when i open it after the browser is loaded properly, in other words, if i open my profile section first and wait for the browser to finish loading and then navigate back to the home page, the countdown works fine . But if i reload the page from home page, it keeps on spinning.
`/* eslint-disable @typescript-eslint/no-unused-vars */
import {
Component,
OnInit,
OnDestroy,
ViewChild,
afterNextRender,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { Carousel, CarouselModule } from 'primeng/carousel';
import { ButtonModule } from 'primeng/button';
import { TagModule } from 'primeng/tag';
import { AuctionService } from '../../../services/auction/auction.service';
import { interval, Subscription } from 'rxjs';
interface Auction {
id: number;
auction_end_date: string;
timeRemaining?: string;
[key: string]: any;
}
@Component({
selector: 'app-auctions',
standalone: true,
imports: [
CommonModule,
RouterModule,
CarouselModule,
ButtonModule,
TagModule,
],
templateUrl: './auctions.component.html',
styleUrl: './auctions.component.scss',
})
export class AuctionsComponent implements OnInit {
@ViewChild('carousel') carousel!: Carousel;
@ViewChild('carouselFuture') carouselFuture!: Carousel;
liveAuctions: Auction[] = [];
futureAuctions: Auction[] = [];
groupedFutureAuctions: any[][] = [];
responsiveOptions: any[] | undefined;
private countdownSubscription: Subscription | null = null;
constructor(private auctionService: AuctionService) {}
ngOnInit(): void {
this.responsiveOptions = [
{
breakpoint: '1199px',
numVisible: 1,
numScroll: 1,
},
{
breakpoint: '991px',
numVisible: 2,
numScroll: 1,
},
{
breakpoint: '767px',
numVisible: 1,
numScroll: 1,
},
];
this.fetchLiveAuctions();
this.fetchFutureAuctions();
}
startCountdown(): void {
this.countdownSubscription = interval(1000).subscribe(() => {
this.liveAuctions = this.liveAuctions.map((auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(auction.auction_end_date),
}));
this.futureAuctions = this.futureAuctions.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(auction.auction_end_date),
}));
this.groupFutureAuctions();
});
}
groupFutureAuctions(): void {
this.groupedFutureAuctions = [];
for (let i = 0; i < this.futureAuctions.length; i += 4) {
this.groupedFutureAuctions.push(this.futureAuctions.slice(i, i + 4));
}
}
fetchLiveAuctions(): void {
this.auctionService
.getLiveAuctions()
.then((result: any) => {
// console.log('Result in fetch live auctions', result.data);
if (result?.data) {
this.liveAuctions = result.data.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(
auction.auction_end_date
),
}));
}
this.startCountdown();
})
.catch((error) => {
console.error('Error fetching live auctions:', error);
});
}
fetchFutureAuctions(): void {
this.auctionService
.getFutureAuctions()
.then((result: any) => {
console.log('Result in fetch future auctions', result.data);
if (result?.data) {
this.futureAuctions = result.data.map((auction: Auction) => ({
...auction,
timeRemaining: this.calculateTimeRemaining(
auction.auction_end_date
),
}));
}
this.groupFutureAuctions();
})
.catch((error) => {
console.error('Error fetching live auctions:', error);
});
}
calculateTimeRemaining(endDate: string): string {
if (!endDate) return 'Invalid date';
const end = new Date(endDate).getTime();
if (isNaN(end)) return 'Invalid date';
const now = Date.now();
const diff = end - now;
if (diff <= 0) return 'Auction ended';
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return `${days}D ${hours}H ${minutes}M ${seconds}S`;
}
prevLive(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carousel?.navBackward(event);
}
}
nextLive(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carousel?.navForward(event);
}
}
prevFuture(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carouselFuture?.navBackward(event);
}
}
nextFuture(event: Event): void {
event.preventDefault();
if (event instanceof MouseEvent || event instanceof TouchEvent) {
this.carouselFuture?.navForward(event);
}
}
getSeverity(status: string) {
switch (status) {
case 'INSTOCK':
return 'success';
case 'LOWSTOCK':
return 'warning';
case 'OUTOFSTOCK':
return 'danger';
default:
return 'info';
}
}
trackByAuctionId(index: number, auction: any): number {
return auction.id;
}
}
`
so is there any other way to implement the counter, other than using interval??
Share Improve this question edited Jan 24 at 10:49 Sachin Kizhakkepurath asked Jan 24 at 7:30 Sachin KizhakkepurathSachin Kizhakkepurath 312 bronze badges2 Answers
Reset to default 0You might have SSR enabled, so it waits for the component to become stable which when using interval
does not happen, since it's an observable that does not end. So the solution is to execute the countdown logic only on the browser, using the afterNextRender
function (Which executes only on the browser).
ngOnInit() {
...
afterNextRender(() => {
this.fetchLiveAuctions();
});
}
Another option is to use Hybrid rendering which defines whether the route is to run on the client or the server.
ng add @angular/ssr --server-routing
Then in the routing you can define:
// app.routes.server.ts
import { RenderMode, ServerRoute } from '@angular/ssr';
export const serverRoutes: ServerRoute[] = [
{
path: 'countdown',
renderMode: RenderMode.Client,
},
...
i have used window.setInterval for solving this issue and it is working well now, and instead of invoking the function inside onInit, now I have moved it into afterViewInit
ngAfterViewInit(): void {
this.startPersistentCountdown();
}
startPersistentCountdown(): void {
this.stopCountdown();
this.zone.runOutsideAngular(() => {
this.countdownTimer = window.setInterval(() => {
this.zone.run(() => {
this.updateAuctionTimers(this.liveAuctions);
this.updateAuctionTimers(this.futureAuctions);
this.groupFutureAuctions();
this.cdr.markForCheck();
});
}, 1000);
});
}
本文标签: Implementing countdown in angular causes browser to load infinitelyStack Overflow
版权声明:本文标题:Implementing countdown in angular causes browser to load infinitely - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738439641a2086882.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论