1
Vývoj / Re:Ako zachytit ukoncenie JS Web Workeru?
« Poslední příspěvek od Wangarad kdy Dnes v 17:59:52 »Bohužiaľ, v Shared Workers ani v bežných Web Workers neexistuje žiadna natívna udalosť typu beforeunload alebo iná udalosť, ktorá by sa spúšťala tesne pred ich ukončením. Akonáhle posledné spojenie (port) k Shared Workeru zanikne, prehliadač jednoducho ukončí jeho beh bez nejakej "poslednej šance" na vykonanie čistiacich operácií z jeho vnútra.
Dôvody a detaily:
Shared Worker životný cyklus:
Shared Worker je udržiavaný nažive pokiaľ existuje aspoň jeden otvorený komunikačný kanál (port) z niektorej zo stránok. Ak máte napríklad dve otvorené karty a obe sú pripojené k rovnakému Shared Workeru, worker beží. Ak jednu kartu zavriete alebo refreshnete, jej porty sa ukončia, no Shared Worker pokračuje v behu, pokiaľ druhá karta je stále pripojená. Ak ale zatvoríte či refreshnete poslednú kartu, ktorá ho používa, Shared Worker zanikne.
Neexistencia "cleanup" eventov v workeroch:
Na rozdiel od hlavného okna (Window) v prehliadači, kde existujú udalosti ako beforeunload či unload, workery (či už Dedicated alebo Shared) takéto mechanizmy nemajú. Dôvodom je, že workery bežia v izolovanom vlákne a ich ukončenie je riadené zo strany prehliadača bez explicitného upozornenia workerov.
Prečo to nejde len vo workeri?
Vývojári bežne riešia „čistenie“ websocketového spojenia alebo iné cleanup akcie pri udalostiach na strane hlavnej stránky – napr. pri beforeunload odoslať do workera správu na uzavretie websocketu. Ak to však striktne nechcete robiť z hlavnej stránky, potom vám v rámci API Shared Workeru neostáva žiadna priama cesta. Worker nevie "sám od seba", že bude ukončený – on jednoducho skončí, keď niet žiadnych portov.
Možné obídenie problému (workaround):
Nepriame signály: Aj keď to nechcete, najčastejšie riešenie je využitie rozhrania medzi stránkou a workerom. Pri beforeunload vo Window odoslať do Shared Workera správu v štýle "odhlasujem sa, uzavri websocket". Ak je to posledný port, tak worker vykoná cleanup pred ukončením.
Timeout / Heartbeat mechanizmus vo workeri: Môžete vo workeri implementovať mechanizmus, ktorý periodicky kontroluje počet otvorených spojení (portov) a pokiaľ zistí, že žiadne nie sú (t.j. odpojí sa posledný port), tak uzavrie websocket. Keďže po odpojení posledného portu už worker žije len veľmi krátko, je isté, že s týmto timeoutom/heartbeatom bude code spustený predtým, než browser worker zruší. Toto však môže byť nespoľahlivé, ak browser ukončí worker príliš promptne – závisí to od implementácie prehliadača. Niektoré prehliadače worker ukončujú takmer okamžite, iné dávajú "pár milisekúnd navyše". Tento prístup nie je 100% garantovaný.
Architektonické úpravy backendu: Ak viete zmeniť správanie na strane servera, môžete upraviť logiku tak, aby "stare" spojenia po novom pripojení od toho istého klienta boli ihneď invalidované. Teda ak sa znova prihlási rovnaký klient s rovnakou identitou, staré spojenie sa na serveri ukončí. Tým vyriešite problém s čakaním na timeout.
Dôvody a detaily:
Shared Worker životný cyklus:
Shared Worker je udržiavaný nažive pokiaľ existuje aspoň jeden otvorený komunikačný kanál (port) z niektorej zo stránok. Ak máte napríklad dve otvorené karty a obe sú pripojené k rovnakému Shared Workeru, worker beží. Ak jednu kartu zavriete alebo refreshnete, jej porty sa ukončia, no Shared Worker pokračuje v behu, pokiaľ druhá karta je stále pripojená. Ak ale zatvoríte či refreshnete poslednú kartu, ktorá ho používa, Shared Worker zanikne.
Neexistencia "cleanup" eventov v workeroch:
Na rozdiel od hlavného okna (Window) v prehliadači, kde existujú udalosti ako beforeunload či unload, workery (či už Dedicated alebo Shared) takéto mechanizmy nemajú. Dôvodom je, že workery bežia v izolovanom vlákne a ich ukončenie je riadené zo strany prehliadača bez explicitného upozornenia workerov.
Prečo to nejde len vo workeri?
Vývojári bežne riešia „čistenie“ websocketového spojenia alebo iné cleanup akcie pri udalostiach na strane hlavnej stránky – napr. pri beforeunload odoslať do workera správu na uzavretie websocketu. Ak to však striktne nechcete robiť z hlavnej stránky, potom vám v rámci API Shared Workeru neostáva žiadna priama cesta. Worker nevie "sám od seba", že bude ukončený – on jednoducho skončí, keď niet žiadnych portov.
Možné obídenie problému (workaround):
Nepriame signály: Aj keď to nechcete, najčastejšie riešenie je využitie rozhrania medzi stránkou a workerom. Pri beforeunload vo Window odoslať do Shared Workera správu v štýle "odhlasujem sa, uzavri websocket". Ak je to posledný port, tak worker vykoná cleanup pred ukončením.
Timeout / Heartbeat mechanizmus vo workeri: Môžete vo workeri implementovať mechanizmus, ktorý periodicky kontroluje počet otvorených spojení (portov) a pokiaľ zistí, že žiadne nie sú (t.j. odpojí sa posledný port), tak uzavrie websocket. Keďže po odpojení posledného portu už worker žije len veľmi krátko, je isté, že s týmto timeoutom/heartbeatom bude code spustený predtým, než browser worker zruší. Toto však môže byť nespoľahlivé, ak browser ukončí worker príliš promptne – závisí to od implementácie prehliadača. Niektoré prehliadače worker ukončujú takmer okamžite, iné dávajú "pár milisekúnd navyše". Tento prístup nie je 100% garantovaný.
Architektonické úpravy backendu: Ak viete zmeniť správanie na strane servera, môžete upraviť logiku tak, aby "stare" spojenia po novom pripojení od toho istého klienta boli ihneď invalidované. Teda ak sa znova prihlási rovnaký klient s rovnakou identitou, staré spojenie sa na serveri ukončí. Tým vyriešite problém s čakaním na timeout.