#javascript #angular #typescript
#язык JavaScript #угловой #машинописный текст
Вопрос:
Я установил таймер обратного отсчета в машинописном виде на свою веб-страницу на домашней странице. Но когда я переключаюсь на другую страницу, я каждую секунду получаю ошибку консоли.
.TS
countDown() { var countDownDate = new Date("Jan 1, 2022 00:00:00").getTime(); // Update the count down every 1 second var x = setInterval(function () { var now = new Date().getTime(); // Find the distance between now an the count down date var distance = countDownDate - now; var days = Math.floor(distance / (1000 * 60 * 60 * 24)); var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); var seconds = Math.floor((distance % (1000 * 60)) / 1000); // Display the result in an element with id="demo" var contadorElement = document.getElementById("contador") as HTMLElement; // lt;- Line 37 contadorElement.innerHTML = days "d " hours "h " minutes "m " seconds "s "; if (distance lt; 0) { clearInterval(x); contadorElement.innerHTML = "EXPIRED"; } }, 1000); }
.HTML
lt;p id="contador" style="font-size:30px"gt;lt;/pgt;
Приведенный выше код работает в разделе » localhost:4200/». Однако, если я перейду в «localhost:4200/anotherStuf» (например) Я получаю эту ошибку консоли каждую секунду:
core.js:6456 ERROR TypeError: Cannot set properties of null (setting 'innerHTML') at home.component.ts:37 at timer (zone.js:2561) at ZoneDelegate.invokeTask (zone.js:406) at Object.onInvokeTask (core.js:28661) at ZoneDelegate.invokeTask (zone.js:405) at Zone.runTask (zone.js:178) at invokeTask (zone.js:487) at ZoneTask.invoke (zone.js:476) at data.args.lt;computedgt; (zone.js:2541)
Есть какие-нибудь мысли?
Ответ №1:
Когда вы меняете свою страницу, часть DOM contador
, в которой находится ваш элемент, уничтожается. Поскольку вы не очищаете свой setInterval
в ngOnDestroy
крючке, ваш код все еще выполняется, даже когда вы удаляетесь (т. Е. ваш компонент уничтожается). Это привело бы к ошибке в духе cannot read undefined of contadorElement (reading: innerHTML)
или чему-то подобному.
Решение простое: очистите свой setInterval
, чего вы можете добиться, вызвав clearInterval
ngOnDestroy
хук, используя возвращаемое значение вашего setInterval
в качестве параметра.
private interval; countDown() { this.interval = setTimeout(() =gt; { /* Omitted for readability */}, 1000); } ngOnDestroy() { clearInterval(this.interval); }
Поскольку вы уже очищаете интервал, когда расстояние достигает 0, вы можете немного отполировать его, установив переменную в undefined
значение или null
после очистки интервала и вызывая только clearInterval
тогда, когда вы еще не остановили его.
private interval; countDown() { this.interval = setTimeout(() =gt; { /* Omitted for readability */ if (distance lt; 0) { this.stopInterval(); contadorElement.innerHTML = "EXPIRED"; } }, 1000); } ngOnDestroy() { clearInterval(this.interval); } private stopInterval() { if (this.interval) { clearInterval(this.interval); this.interval = null; } }
Если вы не можете остановить таймер ngOnDestroy
(если, например, ваш код находится внутри службы, и вы не хотите вызывать stopCountDown
метод ngOnDestroy
), вам придется проверить, существует ли элемент в каждом цикле setInterval, и, возможно, уничтожить интервал, если он больше не существует.
countDown() { // Update the count down every 1 second var x = setInterval(function () { /* Omitted for readability */ var contadorElement = document.getElementById("contador") as HTMLElement; if (contadorElement) { contadorElement.innerHTML = days "d " hours "h " minutes "m " seconds "s "; } else { clearInterval(x); } if (distance lt; 0) { clearInterval(x); contadorElement.innerHTML = "EXPIRED"; } }, 1000); }