Autor Zpráva
kajaman
Profil
Mám stránku, na které se děje několik věcí najednou:
1, zobrazuje se aktuální cena (jedná se o aukci)
2, zobrazuje se akutální doba, která zbývá do konce aukce
3, zobrazuje se chat

Všechny tyto věci jsou dotazovány přes Ajax a PHP, vytvořil jsem 3 samostatné XMLHttpRequesty,
Odpočet času se akualizuje po 1 sekundě, ostatní dvě informace po 3 sekundách, abych to tolik
nepřetěžoval. Nevím, jesli to nestíhá server, nebo prohlížeč, nebo připojení...

Mohli byste se na to prosím kouknout a okomentovat, jestli jsem to třeba nestvořil nějak
brutálně neefektivně? Moc děkuju.

var httpRequest;
var httpRequest2;
var httpRequest2;

function createXMLHTTP()
{
  if (window.ActiveXObject) {
    httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
    httpRequest2 = new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    httpRequest = new XMLHttpRequest();
    httpRequest2 = new XMLHttpRequest();
  }
}

function createXMLHTTP2()
{
  if (window.ActiveXObject) {
    httpRequest3 = new ActiveXObject("Microsoft.XMLHTTP");
  } else {
    httpRequest3 = new XMLHttpRequest();
  }
}

function obnov()
{
  createXMLHTTP();
  httpRequest.open("GET", "/public/akce/index/komunikator" , true);
  httpRequest2.open("GET", "/public/akce/index/cena" , true);
  httpRequest.onreadystatechange = zpracuj;
  httpRequest2.onreadystatechange = zpracujCenu;
  httpRequest.send(null);
  httpRequest2.send(null)
}

function obnovCas()
{
      createXMLHTTP2();
      httpRequest3.open("GET", "/public/akce/index/odpocet" , true);
      httpRequest3.onreadystatechange = zpracujOdpocet;
      httpRequest3.send(null)
}

function zpracuj()
{
  if (httpRequest.readyState == 4)
  {
    var komunikator = document.getElementById('komunikator');
    while (komunikator.childNodes.length > 0) {
        komunikator.removeChild(komunikator.childNodes[0]);
    }

    var vysledky = httpRequest.responseXML;
    var zpravy = '';
    var zpravy = vysledky.getElementsByTagName('zprava');
    for (var i = 0; i < zpravy.length; i++) {
        var item = document.createElement('li');
        if ( i % 2 == 0) {
            item.setAttribute('class', 'barevnyRadek');
        }
        var obsah = document.createTextNode(zpravy[i].childNodes[0].nodeValue);
        item.appendChild(obsah);
        komunikator.appendChild(item);
    }
  }
}

function zpracujCenu()
{
  if (httpRequest2.readyState == 4)
  {
    var nejlepsi = document.getElementById('nejlepsi');
    var vysledky = httpRequest2.responseXML;
    var nejlepsiCena = vysledky.getElementsByTagName('cena');
    nejlepsi.innerHTML = nejlepsiCena[0].childNodes[0].nodeValue;
  }
}

function zpracujOdpocet()
{
  if (httpRequest3.readyState == 4)
  {
    var odpocet = document.getElementById('odpocet');
    var vysledky = httpRequest3.responseXML;
    var odpoved = vysledky.getElementsByTagName('cas');
    var cas = odpoved[0].childNodes[0].nodeValue;

    if (cas == 'ukoncena') {
        odpocet.innerHTML = 'Akce byla ukončena';
    } else {
        odpocet.innerHTML = 'Do ukončení zbývá: ' + cas;
    }
  }
}

obnov();
obnovCas();
$interval = window.setInterval("obnov()", 3000);
$interval2 = window.setInterval("obnovCas()", 1000);


Chamurappi
Profil
Reaguji na kajamana:
Je to průměrně ošklivý kód. Zbytečně upovídaný, totožné úkony (třeba tvorbu XMLHttpRequestu) by měla dělat jedna funkce. Proměnnou httpRequest3 nikde nedeklaruješ, httpRequest2 deklaruješ dvakrát.

item.setAttribute('class', 'barevnyRadek');
Tohle nepojede v Exploreru, proč nepoužíváš vlastnost className?

Odpočet času se akualizuje po 1 sekundě
Pro případ, že by čas na straně návštěvníka běžel jinak rychle, než čas na serveru? World Wide Web sice vznikl v CERNu, ale zatím na něm není nutné počítat s černou dírou či jinými časoprostorovými anomáliemi.
kajaman
Profil
Chamurappi:
Pro případ, že by čas na straně návštěvníka běžel jinak rychle, než čas na serveru? World Wide Web sice vznikl v CERNu, ale zatím na něm není nutné počítat s černou dírou či jinými časoprostorovými anomáliemi.

je důležité časování té aukce, takže se musí zobrazovat čas, který běží na serveru...
kajaman
Profil
Chamurappi:
totožné úkony (třeba tvorbu XMLHttpRequestu) by měla dělat jedna funkce.

dvě fce,protože jedna vytvoří httpRequest a httpRequest2, které potřebuji 1x za 3 vtřeřiny a ta druhá dělá httpRequest3, kterou potřebuji 1x za 1 vteřinu
Chamurappi
Profil
Reaguji na kajamana:
je důležité časování té aukce, takže se musí zobrazovat čas, který běží na serveru
Ale sekunda na straně serveru trvá stejně jako sekunda na straně klienta, takže je naprosto nesmyslné bombardovat server požadavkem každou sekundu, aby mi řekl, že uběhla sekunda.

dvě fce,protože jedna vytvoří httpRequest a httpRequest2
Ne, na vytvoření, které provádíš třikrát stejně, stačí jedna funkce. A nepotřebuješ globální proměnné.
kajaman
Profil
OK, díky za kritiku.
Lopata
Profil
Chamurappi:
Ale sekunda na straně serveru trvá stejně jako sekunda na straně klienta, takže je naprosto nesmyslné bombardovat server požadavkem každou sekundu, aby mi řekl, že uběhla sekunda.
To není úplně pravda. Nevím, co Kajman s tím časováním tvoří, ale jestli potřebuje opravdu přesný čas, serveru se ptát musí.
Javascript se totiž postupně zpožďuje
Bubák
Profil
Lopata:
Tak znova a pomalu.
V počítači jsou hodiny s dostatečnou přesností. Javascriptový časovač použiješ jen k tomu, aby se, třeba co (přibližně) sekundu "podíval", kolik přesně uběhlo času.
Lopata
Profil
Bubák:
Já to samozřejmě chápu. Jen jsem zpochybnil tvrzení Chamurappiho, že sekunda na straně serveru trvá stejně jako sekunda na straně klienta, protože to nemusí být vždy pravda.

V počítači jsou hodiny s dostatečnou přesností
Dostatečnost je relativní. Počítáme-li z odchylkou cca 50ms za vteřinu, každou minutu se časování odchýlí o tři sekundy. Kajman si zvolil cestu AJAXu, a proto mu o přesný čas zjevně jde. A přesný čas je přesný čas, protože 60 != 63. Myslím, že bychom mu měli raději pomoci učesat ten kód, než kritizovat myšlenku jako takovou.

(přibližně)
Zpochybňováním přesnosti javascriptového časovače se mnou jen souhlasíš.
Bubák
Profil
Lopata:
Zpochybňováním přesnosti javascriptového časovače se mnou jen souhlasíš.
Takže naposled:
Nepřesný javascriprový časovač se použije jen k tomu, aby se skript co určitou dobu "podíval" na přesné systémové hodiny.
Přesnost hodin přece nezáleží na tom, jak často se na ně dívám.
Chamurappi
Profil
Reaguji na Lopatu:
Jen jsem zpochybnil tvrzení Chamurappiho
Spíš poukazuješ na vady špatného postupu, který sis sám domyslel z mého pravdivého tvrzení.

Myslím, že bychom mu měli raději pomoci učesat ten kód, než kritizovat myšlenku jako takovou.
Za neučesaný kód si zaslouží pohlavek, za evidentně hloupou myšlenku, která při větší návštěvnosti položí server, padáka.
Mimochodem, tazatelem není kolega Kajman, ale kajaman.
_es
Profil
Lopata:
Javascript se totiž postupně zpožďuje
V tom článku nie je, že sa môže oneskorovať samotná hodnota času v JavaScripte, ale len spúšťanie funkcie uvedenej v SetInterval.
Nejako celkom nerozumiem, o čo v tom "triku" ide. Skôr to vyzerá na to, že niekto nepochopil "problém". Užitočné by to mohlo byť, ak by ten skript mal bežať rádovo v dňoch a interval dotazovania serveru na presný čas by bol rádovo v hodinách.

Počítáme-li z odchylkou cca 50ms za vteřinu, každou minutu se časování odchýlí o tři sekundy.
Ak sa nebude spoliehať na to, že sa časovač SetInterval spúšťa v presných intervaloch, ale radšej sa bude vždy zisťovať priamo samotná hodnota času v JS, tak to určite nemôže nastať.
kajaman
Profil
Jak jsem nahoře naznačil, jde o aukci, takže potřebuji pro všechny přihlášené zobrazovat serverový čas a pokud možno ve stejný okamžik - s přesností na 1 sekundu jim ukončit možnost přihodit.
Samozřejmě, že Chamurappi má pravdu, nelze „bombardovat server požadavkem každou sekundu, aby mi řekl, že uběhla sekunda.

Pravdu mají částečně i ostatní, nelze se spolehnout na prostředí klienta. Zvolil jsem kompromis: budu v pravidelných cyklech (cca 30s) ověřovat čas na serveru a mezi tím budu odpočítávat předaný čas po sekundě. Tím snížím zátěž na server a budu mít dostatečnou přesnost odpočtu času.
Chamurappi
Profil
Reaguji na kajamana:
budu v pravidelných cyklech (cca 30s) ověřovat čas na serveru
I tohle je špatný kompromis. Nemusíš se vůbec opakovaně ptát serveru. Co je na tom tak nepochopitelného? Čas skutečně běží všude stejně rychle.

mezi tím budu odpočítávat předaný čas po sekundě
Proč odpočítávat? Proč nevyjdeš z rozdílu času u klienta?
kajaman
Profil
Chamurappi:
I tohle je špatný kompromis.

proč je to špatně? Synchronizaci bys neřešil? Co kdyby si někdo přenastavil v průběhu aukce systémový čas a potom řešil, že "mu to ukazovalo ještě 10 minut"... tím by diskreditoval celý systém (ačkoli by neměl samozřejmě pravdu).

Proč odpočítávat? Proč nevyjdeš z rozdílu času u klienta?
můžu odpočítávat předaný serverový čas (resp. interval do ukončení aukce), nebo zobrazovat čas na klientově systému (resp. interval do konce aukce, který vypočtu ze systémového času a rozdílu oproti serverovému častu a času ukončení aukce). Je v tom druhém nějaká výhoda?
Joker
Profil
kajaman:
Synchronizaci bys neřešil?
Synchronizace samozřejmě nutná je, ale stačí ji udělat jednou na začátku.
Já bych řekl, že pokud uběhlo třeba 5 minut systémového času na klientovi, lze s pravděpodobností nejméně 99,5% (můj odhad) čekat, že to je i 5 minut na serveru.

Co kdyby si někdo přenastavil v průběhu aukce systémový čas a potom řešil, že "mu to ukazovalo ještě 10 minut"... tím by diskreditoval celý systém
Jak? Proč? Co by tím docílil?
I kdyby byla synchronizace každou sekundu, stejně to půjde manipulovat, třeba přes Javascript zadaný do adresního řádku prohlížeče.
Anebo si třeba v Opeře na stránce nechám vyhodit nějaký alert, zaškrtnu "zastavit provádění skriptů na této stránce"... a zastaví se i odpočet.

Mimochodem, jestli chcete pojistku proti změně systémového času během odpočtu, stačí vyvolat novou synchronizaci v případě, že nová hodnota odpočtu se od staré liší třeba o více než 3 sekundy.
Pokud se odpočet aktualizuje každou sekundu, vlivem nepřesnosti Javascriptu může nová hodnota odpočtu být o 0, 1 nebo 2s jiná než ta předchozí. Větší rozdíl by neměl nastat.

můžu odpočítávat předaný serverový čas (...), nebo zobrazovat čas na klientově systému (resp. interval do konce aukce, který vypočtu ze systémového času a rozdílu oproti serverovému častu a času ukončení aukce). Je v tom druhém nějaká výhoda?
Ano. Jelikož to načasování Javascriptem není úplně přesné (samotný časovač má alespoň tak 20-30 milisekund rozptyl a provádění té funkce taky nějakou dobu trvá), první způsob se bude postupně vzdalovat od skutečnosti.
Podle mých zkušeností to vyrobí rozdíl několik sekund každou minutu. Naopak ten druhý způsob (na začátku stanovit rozdíl mezi klientem a serverem a pak počítat podle klienta) bude (v rámci nějakých rozumných hranic) přesný.
kajaman
Profil
Joker:
děkuji, promyslím to.
_es
Profil
kajaman:
Co kdyby si někdo přenastavil v průběhu aukce systémový čas a potom řešil, že "mu to ukazovalo ještě 10 minut"... tím by diskreditoval celý systém
To treba správne definovať pravidlá, ak bude určené, že aukcia bude ukončená v nejaký presný UTC čas, tak to odpočítavanie bude len pomocné a návštevník si bude sám na vine, že má zle nastavený systémový čas alebo si ho počas aukcie prenastavil. To zlé nastavenie sa dá riešiť tým rozdielom, ako ti radil Chamurappi.
Chamurappi
Profil
Vlezl mi do psaní odpovědi poměrně dobrý oběd, takže budu asi trochu redundantní, ale mazat se mi to nechce :-)


Reaguji na kajamana:
Synchronizaci bys neřešil?
Ne.

Co kdyby si někdo přenastavil v průběhu aukce systémový čas a potom řešil, že "mu to ukazovalo ještě 10 minut"
Předpokládám, že čas odměřovaný na straně klienta nemá dopad na funkčnost na straně serveru. Takže když si na své straně s něčím úmyslně hne (ať už jde o změnu systémového času, nebo o spuštění bookmarkletu přepisujícího nějakou tvoji proměnnou), nemůže si nárokovat stoprocentní funkčnost.
Kromě odpočtu budeš asi někde ukazovat i skutečný čas konce aukce, ne? Takže ten odpočet stejně bude jen orientační.

Je v tom druhém nějaká výhoda?
Lepší přesnost (respektive nepřesnost neměnná v čase), menší nároky na připojení i na zátěž serveru.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: