При использовании функции render библиотека
самостоятельно обновляет DOM-элементы через внутренние таймеры. Однако
бывают ситуации, когда необходимо запустить обновление немедленно — без
ожидания следующего цикла таймера.
После вызова render(nodes, locale) библиотека:
Первое обновление происходит синхронно в момент вызова
render. Последующие — по таймеру.
datetime у элемента.relativeDate.Самый простой способ — вызвать render ещё раз:
import { cancel, render } from 'timeago.js';
const nodes = document.querySelectorAll('.time');
// Остановить предыдущие таймеры
cancel(nodes);
// Запустить новый цикл обновления
render(nodes, 'ru');
Это сбрасывает все таймеры и инициирует немедленное обновление.
import { cancel, render } from 'timeago.js';
const el = document.querySelector('#time');
// Сменить дату
el.setAttribute('datetime', new Date().toISOString());
// Принудительно переинициализировать
cancel(el);
render(el, 'ru');
При использовании format (без render)
каждый вызов всегда возвращает актуальный результат — нет кэширования
или отложенного обновления:
import { format } from 'timeago.js';
function refreshTime(date, element) {
element.textContent = format(date, 'ru');
}
Вызов refreshTime в любой момент гарантирует актуальное
значение.
Когда пользователь возвращается на вкладку, время могло сильно измениться:
import { cancel, render } from 'timeago.js';
document.addEventListener('visibilitychange', () => {
if (!document.hidden) {
const nodes = document.querySelectorAll('[data-timeago]');
cancel(nodes);
render(nodes, 'ru');
}
});
В React самый простой способ принудить повторный рендер — изменить
key компонента:
import { useState } from 'react';
import { format } from 'timeago.js';
function TimeAgo({ date }) {
return <time>{format(date, 'ru')}</time>;
}
function App() {
const [refreshKey, setRefreshKey] = useState(0);
return (
<div>
<TimeAgo key={refreshKey} date="2025-05-26T08:00:00Z" />
<button onCl ick={() => setRefreshKey(k => k + 1)}>Обновить</button>
</div>
);
}
import { useEffect, useRef } from 'react';
import { render, cancel } from 'timeago.js';
function TimeNode({ date }) {
const ref = useRef(null);
useEffect(() => {
if (!ref.current) return;
cancel(ref.current);
render(ref.current, 'ru');
return () => cancel(ref.current);
}, [date]); // пересоздаёт таймер при смене даты
return <time ref={ref} dateTime={date}></time>;
}
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import { render, cancel } from 'timeago.js';
const props = defineProps({ date: String });
const el = ref(null);
function init() {
if (!el.value) return;
cancel(el.value);
render(el.value, 'ru');
}
onMounted(init);
onBeforeUnmount(() => cancel(el.value));
// Принудительно обновлять при смене даты
watch(() => props.date, init);
</script>
<template>
<time ref="el" :datetime="date"></time>
</template>
import { cancel, render } from 'timeago.js';
function refreshAll(locale = 'ru') {
const nodes = document.querySelectorAll('[datetime]');
cancel(nodes);
render(nodes, locale);
}
// Обновлять каждые 5 минут
setInterval(refreshAll, 5 * 60 * 1000);
import { cancel, render } from 'timeago.js';
socket.on('new_post', (post) => {
// Добавить новый элемент
addPostToDOM(post);
// Обновить все временны́е метки
const nodes = document.querySelectorAll('.post-time');
cancel(nodes);
render(nodes, 'ru');
});
При каждом вызове render создаются новые таймеры. Без
предварительного cancel старые таймеры продолжают работать,
что приводит к дублированию обновлений и утечкам памяти.
Правильная последовательность:
cancel(nodes); // сначала остановить старые
render(nodes, locale); // затем запустить новые