LINUX.ORG.RU

Часы отбивают на один час больше. Иногда. И только в Firefox.

 , , ,


0

1

Имеется такая страница. Часы на ней должны в начале каждого часа отбивать столько раз, сколько сейчас часов. В 9 утра отбить 9 раз, в 15:00 — три раза и т.д.

Вроде всё работает, но есть странная проблема: иногда они отбивают на один час больше, чем надо. Из сегодняшних наблюдений:

12:00 — всё ок

13:00 — всё ок

14:00 — 3 удара в колокол вместо положенных двух

15:00 — 4 удара

16:00 — всё ок. Но при вызове функции из консоли в 16:04 отбил 5 раз.

19:00 — всё ок. Спустя несколько минут вызываю функцию из консоли - отбивает 8 раз.

Проблема наблюдается в Firefox — как десктоптном, так и на Android. В Opera и Chromium (опять же: и на ПК, и на смартфоне) всё в порядке.

Вот функция, вызываемая в начале нового часа. Её же я вызывал через консоль браузера.

function newHour() {
    let now = new Date();
    
    // Который час?
    full_hours = now.getHours();

    // Потребен 12-часовой формат. Аще час больше 12 - надо из оного 12 вычесть. Например, 16-12==4
    if (full_hours > 12) {
        full_hours -= 12;
    }

    // Аще средонощие, отбить двана́десять
    if (full_hours == 0) {
        full_hours = 12;
    }

    // Аще ныне 1 час, то благовестник отбивает дважды.
    // Сего ради костыль: аще full_hours == 1, умножать их на 2834 милисекунд не благословляется!
    if (full_hours == 1) {
        playback(b1);
    }
    else {
        // Первый удар благовестника будет не сразу по запуску функции, но через 2834 мсек
        // Посему один раз отбиваем ДО запуска функции, а затем бьём остальные (сколько там останется)
        playback(b1);
        let timerId = setInterval(() => { playback(b1); }, 2834);
        console.log("Hours: " + full_hours);

        /* Один "лишний" удар уже был в начале, до setInterval'а, посему теперь надо отбить на 1 меньше.
           Но сие не касается FIREFOX'а. Ему почему-то надо оставить full_hours, как есть. 
           Поэтому проверяем браузер и по итогам оставляем full_hours без изменений (вычитаем 0) (Firefox)
           или вычитаем 1 (все остальные)
        */
        let crutch = 1;
        if (navigator.userAgent.includes("Firefox")) {
            console.log("Тревога: FIREFOX DETECTED! Костыль активирован!");
            crutch = 0;
            console.log("The crutch is " + crutch + " now");
        }
        
        setTimeout(() => { clearInterval(timerId); }, (full_hours - crutch) * 2834); // из еличества часов вычитаем crutch
    }
    }

Имеются ли на ЛОРе тайновидцы, халдеи и гадатели, способные изъяснить происходящее?

И вдогонку вопрос. Можно ли бой курантов организовать с помощью цикла for? Как-то типа

for (i=1; i<full_hours; i++) {
функция_проигрывания_одного_удара_в_колокол;
пожождать_пару_секунд;
}

У меня указанная схема не сработала.



Последнее исправление: Mapper720 (всего исправлений: 1)

Не знаю что это (js?), зачем и почему, но рискну предположить, что «в начале нового часа» иногда происходит до начала часа, например, в 15:59:59 в firefox; выведи полное время вместо «костыля».

dsdqmhsx
()

убери спец. логику для файрфокса из скрипта для начала, потом уже ищи в чём проблема

firkax ★★★★★
()
Ответ на: комментарий от Anoxemian

обычные топики, и их всего 5, ты что-то напутал

firkax ★★★★★
()

Можно ли бой курантов организовать с помощью цикла for?

Я в JS — ноль, но почему бы через тот же for не устанавливать таймаут?

for (i=0; i<full_hours; i++) {
    setTimeout(()=>{playback(b1);}, i*1000);
}
anonymous
()

У тебя нет гарантий, что функции в setInterval и setTimeout выполнятся в том порядке, что ты думаешь, ты же заводишь их на одно и то же время.

goingUp ★★★★★
()

И тут ещё:

if (full_hours > 12)

full_hours = full_hours % 12 || 12;
anonymous
()

Можно ли бой курантов организовать с помощью цикла for? Как-то типа

Сделай функцию, которая принимает параметром количество ударов, бьет один раз, вычитает кол. ударов, и если не ноль, то делает setTimeout себя.

goingUp ★★★★★
()
Ответ на: комментарий от goingUp

Тогда длина звучания будет добавляться к паузе, и звук будет не раз в секунду, а раз в секунду + продолжительность звука. Я хз, может, там как у курантов логика нужна.

izzholtik ★★★
()
Ответ на: комментарий от izzholtik

длина звучания будет добавляться к паузе

Это вряд ли. Хоть автор и не показал код playback, он скорее всего неблокирующий, как и все в ЖС.

goingUp ★★★★★
()

Разбираться в твоей проблеме было лень, поэтому я запилил свою кукушку, может чем поможет, по ссылке можешь нажать js output.

App.svelte

<script>
  import timer from "./timer.js"
  import Cuckoo from "./Cuckoo.svelte"
	
  $: isTimeToCooCoo = $timer.second % 5 === 0
</script>

<pre> 
  [ second: {$timer.second} | minute: {$timer.minute} ] 
</pre>

{#if isTimeToCooCoo}
  <Cuckoo />
{/if}

timer.js

import { readable } from "svelte/store"

const build = () => {
  const now = new Date()

  return { 
    second: now.getSeconds(),
    minute: now.getMinutes() || 60
  } 
}

export default readable(build(), set => {
  const interval = setInterval(() => set(build()), 100)

  return () => clearInterval(interval)
})

Cuckoo.svelte

<script>
  import timer from "./timer.js"
</script>

<figure>
  <p>Coo-coo,<br>bitches!</p>
  <p>{$timer.minute} times!</p>
</figure>

<style>
figure {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-width: 150px;
  max-width: 150px;		
  min-height: 150px;
  max-height: 150px;
  background: red;
  border-radius: 75px;
  margin: 20px auto;
}
p {		
  color: #fff;
  font-weight: 600;
  font-size: 16px;
  margin: 5px;
  text-align: center;
}
</style>

ddidwyll ★★★★
()
Последнее исправление: ddidwyll (всего исправлений: 1)
Ответ на: комментарий от ddidwyll

svelte

Расскажи, пожалуйста, вкратце, почему ты используешь svelte. Спасибо.

Для меня, как не спеца, твой код выглядит очень запутанным и странным. Например, почему вместо const build = () => { ты не написал function build() {?

anonymous
()
Ответ на: комментарий от anonymous

Расскажи, пожалуйста, вкратце, почему ты используешь svelte

Потому что, очень жаль, но ничего близкого по функционалу и удобству для фронта больше нету. Elm тоже хорош, но по своему.

Для меня, как не спеца, твой код выглядит очень запутанным и странным

Это самый обычный ES, от свелте тут только $ - реактивность для сторов и переменных.

Например, почему

Почитай обсуждения в интернете, для меня лично это вопрос стиля и читабельности, как, например, и отсутствие ;

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

по функционалу и удобству

Впрочем это тоже субъективно, но размер бандла, отсутствие рантайма, скорость исполнения и т.д. - критерии более объективные.

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

от свелте тут только $

Ещё обработка export/import немного отличается, ну и {} в html конечно.

ddidwyll ★★★★
()
Последнее исправление: ddidwyll (всего исправлений: 1)
Ответ на: комментарий от ddidwyll

код выглядит очень запутанным и странным

Дело привычки, для меня такой код на порядок более читабелен чем vue и react -код.

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

отсутствие ;

Я заметил :)

Посмотрел скомпилированный вариант. Как по мне, так для такой простой задачи — явно оверкилл. Тут в пять строк можно всё описать, мне кажется.

ничего близкого по функционалу и удобству для фронта больше нету

А что именно лично тебе в svelte больше всего нравится?

anonymous
()
Ответ на: комментарий от ddidwyll

для меня такой код на порядок более читабелен чем vue и react -код

А насколько для тебя сложнее будет писать на голом js? Если будет выбор только между vue и ничего, то что выберешь?

anonymous
()
Ответ на: комментарий от ddidwyll

ничего близкого по функционалу и удобству

https://insights.stackoverflow.com/survey/2021#most-loved-dreaded-and-wanted-webframe-love-dread

Согласно проведённому в прошлом году опросу, этот фреймворк стал одним из самых желаемых, на каком разработчики бы хотели делать приложения. Однако, судя по тому же опросу, в рейтинге используемых фреймоврков лидирует React с почти 40%, в то время как у Svelte их всего 2.75. При этом React (2013) всего на 3 года старше Svelte (2016).

Как думаешь, с чем это может быть связано?

anonymous
()
Ответ на: комментарий от anonymous

А что именно лично тебе в svelte больше всего нравится?

То что я его не замечаю :)

Ну и то, что ничего кроме svelte обычно в проекте не нужно, его достаточно чтобы не задумываясь о внутренностях писать бизнес логику в сторах и её отображение в компонентах без мусора.

явно оверкилл

Привык писать так, чтоб в десятках тыс строк фронта можно было быстро разобраться, добавить новый функционал, таймер например может в десятках компонентов использоваться, или кукушку надо будет отдельно улучшать. Можно было всё в одной кучке, «в 5 строк» написать, но зачем усложнять жизнь себе будущему? :)

А насколько для тебя сложнее будет писать на голом js?

Да тоже самое, если проект большой просто придётся написать свой корявый свелте. Если маленький - будет раздражать писать втрое больше.

Если будет выбор только между vue и ничего, то что выберешь?

Не хочу об этом думать :D

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

То что я его не замечаю :)

Круто. Даже на рекламный слоган смахивает :)

Да тоже самое, если проект большой просто придётся написать свой корявый свелте. Если маленький - будет раздражать писать втрое больше.

Спасибо за классные ответы! Я тебе верю.

anonymous
()
Ответ на: комментарий от anonymous

Как думаешь, с чем это может быть связано?

Потому что вакансий нет, глянь телегу, там есть рускоязычный чатик обсуждений/помощи по свлте, я вроде недавно заходил, но за несколько дней уже 20к комментов пропущенных (или как оно в телеге называется). И есть канал с вакансиями, и там за год сообщений штук 20.

Вообще реактивность на фронте придумал (ну или первый нормально реализовал) создатель свелте, почитай про Рактив. Не всегда удобный интсрумент становится популярным. Почему столько пишут на джаве и пхп? Когда есть всякие хаскели, эликсиры, пони, кложи и т.д.

Я на текущей работе убедил переписать фронт (был реакт + скаладжс + джейквери) на свелте и вроде все довольны, если не сказать больше. На прошлой переписал со вью. А найти работу изначально на свелте не просто.

ddidwyll ★★★★
()
Ответ на: комментарий от anonymous

Спасибо

Да не за что. Я при возможности стараюсь ненавязчиво (в этот раз не получилось) про свелте рассказывать, считаю что мне это выгодно, больше популярности - больше развития для любимого инструмента, больше вакансий ;)

ТС, сорри за оффтоп

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

Я ещё думаю, что это может быть связано с именем разработчика. Одно дело ФБ, а другое — какие-то нонеймы с гитхаба. Понатно, что работодатель скорее выберет индустриальный «стандарт».

на текущей работе

http://0x0.st/ooj4.png

Это прикол такой у вас? Смешно xD В вакансии рубиста всё же просят жиквери, реакт и даже ангуляр. Может старая вакансия?

Спасибо за ссылки, обязательно всё почитаю и посмотрю.

anonymous
()
Ответ на: комментарий от anonymous

какие-то нонеймы с гитхаба

Ну я бы Rich'a Harris'а ноунейном не назвал, в «узких кругах» он давно себе нейм сделал :)

Но конечно для энтерпрайза выбор между ним и ФБ очевиден.

Это прикол такой у вас?

Фига, блин, деанон :D

Ну типо модные, заднеприводные технологии (руби, джс) - основной стек компании был, оттуда reer_tech. Потом уже скала, эликсир, хаскель добавились, не знаю насколько они модные :)

Может старая вакансия?

Ога, я боюсь представить что сейчас там будет

ddidwyll ★★★★
()
Ответ на: комментарий от fernandos

Это шутка была, ну и писал я это минут 15, в основном сражаясь с форматированием в репле.

Да и чуть выше есть ещё о мотивации.

ddidwyll ★★★★
()
Ответ на: комментарий от ddidwyll

Ну типо модные, заднеприводные технологии (руби, джс)

Ору XD

reer

Тогда «rear», наверное, было бы правильнее. Но не моё дело, конечно.

Ладно, заканчиваю тратить твоё время. Спасибо за добрый диалог.

anonymous
()
Ответ на: комментарий от ddidwyll

Дык упрощение же. Реакт так-то библиотека (ну, по крайней мере был), но для удобства его относят к фреймворкам.

fernandos ★★★
()
Ответ на: комментарий от firkax

убери спец. логику для файрфокса из скрипта для начала, потом уже ищи в чём проблема

После этого ситуация меняется на противоположную: проблемной становится первая половина дня. И снова: в Firefox. Попробовал в Опере - в 10:32 отбивает 10 раз, как положено.

6:00 - отбил 5 раз

10:00 - отбил 9 раз

12:00 - отбил 11 раз

13:00 - отбил 1 раз

14:00 - отбил 2 раза

15:00 - отбил 3 раза

17:00 - отбил 5 раз

Mapper720
() автор топика
Последнее исправление: Mapper720 (всего исправлений: 1)
Ответ на: комментарий от ddidwyll

В браузере свелте нет.

Есть. У Svelte есть библиотека времени выполнения и она вклмпиливается в результирующий код.

anonymous
()
Ответ на: комментарий от anonymous

Благодарю, отличная идея. Я с чего-то подобного начинал, но, ЕМНИП, не додумался умножать i на что-то (забыл, что счёт в милисекундах, а не секундах – видимо, привык к Python’у).

Mapper720
() автор топика
Ответ на: комментарий от izzholtik

Мя так и не понял, нужно бить в колокол раз в секунду или делать секундную паузу между ударами?

А это не одно и то же?

Mapper720
() автор топика
Ответ на: комментарий от ddidwyll

Почитал, посмотрел про Svelte. Классный фреймворк язык. Пример с SVG-часами просто поразил! Запилил на его основе свой вариант «кукушки». Пока пилил попарился, конечно, понаступал, так сказать, на грабли. Реактивность я явно ещё не прочувствовал. Наверное я сложную задачу, для новичка в JS, себе взял. Но результат меня устраивает:

<script>
    import { onMount } from 'svelte';
    
    let time = new Date();
    onMount(() => setInterval(() => time=new Date(), 1000));
    $: kuku = Math.floor(time.getSeconds() / 5) || 12;
    
    let rem = 0;
    const dec_rem = () => {if (rem) {setTimeout(dec_rem, 200); rem -= 1;}}
    $: kuku, (() => {rem = kuku; setTimeout(dec_rem, 1000);})();
    $: red = rem ? "red" : "";
</script>

<h2>{time.getSeconds()}s / 5 = <span class={red}>{kuku}</span></h2>
<div>{"🐦".repeat(rem)}</div>

<style>
    h2 {text-align: center;	color: #999;}
    .red {color: red;}
    div {font-size:40px; text-align: center;}
</style>
anonymous
()
Ответ на: комментарий от Mapper720

После этого ситуация меняется на противоположную: проблемной становится первая половина дня. И снова: в Firefox. Попробовал в Опере - в 10:32 отбивает 10 раз, как положено.

Нет, это не противоположная ситуация. Это ситуация нежелательная, но вполне рабочая: у тебя есть баг (в первой половине суток), ты ищешь как его исправить.

А то, что ты предложил в начале темы, не лезет ни в какие рамки: ты дописал к коду бажный костыль и жалуешься что у тебя из-за бажного костыля возник баг. Так делать НЕ надо, надо искать настоящую причину и её исправлять.

Чтобы выяснить в чём проблема, расставь на каждое действие отладочные логи в консоль с числами, от которых всё зависит, и посмотри.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от fernandos

fernandos ★★★ (22.01.22 01:57:52)

А этот дебил всё-же забанился! Ура, товарищи анонимы! Продолжаем в том же духе.

anonymous
()

Код одобряю, оставь как есть.
Хотя, вангую, что к таймауту очистки достаточно добавить 10мс и всё будет работать.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)

Имеются ли на ЛОРе тайновидцы, халдеи и гадатели, способные изъяснить происходящее?

ЛОГИ тебе всё изъяснят. Вставь везде логи. На full_hours, на колбеки setInterval и setTimeout. Много чего узнаешь нового.

И вдогонку вопрос. Можно ли бой курантов организовать с помощью цикла for? Как-то типа

Можно. Асинхронной функцией.

//Делаешь из setTimeout промис:
let sleep = async function(time) {
    return new Promise(ok=>{
        setInterval(() => ok(), time);
    });
}
//Делаешь кукушку
let kukushka = async function(kokoo, count, interval) {
    while (count-- > 0) {
         kokoo(); //функция делает дела на странице
         await sleep(interval);
    }
}
Как-то так.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)

начать надо с того что now.getHours работает в часовом поясе юзера

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.