Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Ajax blokuje ładowanie strony
Forum PHP.pl > Forum > PHP
Boshi
Dwa problemy;
1 Mam notyfikacje zrobione na ajax long polling. Powiedzmy, że działają. Kod
widok
http://pastebin.com/Nc8ynnkD
kontroler
http://pastebin.com/7mPZckUJ

Działa to na takiej zasadzie, że jak w pliku dane.txt zmieni się czas i warunek w pętli się nie spełni to ma zwrócić odpowiedź i wyświetlić powiadomienie.

problem1. Przy każdym przełączeniu podstrony, czas ładowania strony oscyluje w granicach 20-30s, problem jest żadanie ajax, bo jak zakomentuję kod czas spada do ~1s. Zauważyłem, że jeżeli w czasie ładowania strony zmienie sobie ręcznie w pliku czas to strona od razu się ładuje. Podejrzewam, że wtedy pętla nie spełnia warunku i skrypt zwraca odpowiedź i odblokowuje stronę.

problem 2. Jak rozpoznać w pliku który użytkownik zmienił czas? Moim pomysłem jest stworzenie dla każdego zarejestrowanego użytkownika osobny czas a potem w skrypcie rozdzielanie tego i aktualizowanie czasu tylko zalogowanemu użytkownikowi. Np

romek 12321312
franek 2131223432
janek 21321312

I jeżeli np janek wysyła prywatną wiadomość do franka to skrypt wyszukuje franka i jemu zmienia czas w pliku, a że został mu zmieniony czas to dostaje powiadomienie.

powinno to być zrobione wszystko jakoś na websocetach, ale zanim to uruchomię to miną święta 2017r...
maly_swd
A w AJAXsie masz włączone asynchroniczne przesyłanie danych?

async: true
Boshi
Tak.


Na prawdę liczę na pomoc biggrin.gif Jutro się do tego na poważnie zabieram i mam nadzieję to rozgryźć choćbym miał zęby zjeść.
com
może byś sobie tak ten kod zdebugował, skoro to Symfony to masz konsole nawet. Tyle lat na forum i jeszcze się nie nauczył?
Boshi
No, ale co debugować? wiem jaki czas wysyłam do serwera, wiem jaki zwraca, wiem gdzie tkwi błąd i nie wiem jak go rozwiązać. Poza tym nie wiem, czy serwer się nie udusi? np niech w odstępie 10 min wyśle 10 userów wyśle wiadomość prywatną. Każda wiadomość generuje kolejny request z nowym czasem, jak się serwer zachowa z taką pętlą?
com
Weź opisz swój problem bardziej ludzko, bo nie bardzo wiem co Ty pragniesz osiągnąć, bo z tego kodu to za bardzo nic nie wynika wink.gif
nospor
Rety... com.... toz wszystko masz podane jak wol na tacy w czym problem

@Boshi problemem tutaj jest sesja, ktora blokuje wykonywanie innego kodu dopoki jeden sie nie wykona. Usun sesje dla testu a zobaczysz ze bedzie smigac jak ta lala smile.gif
Boshi
Wypróbuję potem Nospor.
Swoją drogą mam wrażenie, że to nie jest dobra droga dla notyfikacji dla wielu użytkowników. Chciałem to zrobić na long polling i działa dobrze dla jednego usera, ale dla wielu...

com
nospor Może jestem ślepy, ale gdzie Ty widzisz sesje? smile.gif

$_POST ?, przecież to powinieneś wyciągać z $request wink.gif

ta pętla się teraz nigdy nie kończy bo $lastDate zawsze zwraca zero wink.gif
nospor
Cytat
nospor Może jestem ślepy, ale gdzie Ty widzisz sesje?
Poprostu czytam objawy... tongue.gif

Cytat
ta pętla się teraz nigdy nie kończy bo zawsze zwraca zero
com ty wez moze w niedziele nie czytaj postow na forum bo masz problem z podstawowa analiza kodu wink.gif
com
nospor niech Ci będzie tongue.gif

  1. $lastDate = isset($_POST['timestamp']) ? $_POST['timestamp'] : 0;


To zwraca zero tongue.gif
bo w Symfony do posta odwołujesz sie tak :
http://symfony.com/doc/2.0/book/http_funda...nses-in-symfony
tongue.gif
nospor
Ty mnie nie ucz podstaw response bo ja je znam.
NIe zmienia to jednak faktu, ze tablica $_POST, przynajmniej dla AJAX, nadal bedzie wypelniona, wiec jego kod dziala jak najbardziej ok tongue.gif
com
wiem że znasz, ok, to mój błąd wink.gif
nospor
Zeby nie bylo: ja sie z toba zgadzam, on to powinien pobierac z obiektu $request. No ale nie zmienia to faktu ze jego $_POST tez dziala wink.gif
Boshi
Panowie, kłócicie się o pierdoły dotyczące kodu zamiast problemu tongue.gif Czy to request czy $_POST jest bez znaczenia totalnie.

Com. Zwraca 0 przy pierwszym requeście (a i tak powinien wysyłać od razu czas generowania strony, ale to szczegół), potem wysyła zwrócony czas z powrotem i porównuje dopóki warunek się nie spełni. To działa, zmieniam sobie recznie czas w pliku (symulacja rzeczywistej zmiany, np wysłanie wiadomości itd) i dostaje powiadomienie. Tyle, że blokuje totalnie działanie strony dopóki znów nie dostanę powiadomienia.

Nospor. Sesja tu nic do rzeczy nie ma. Testowane na zalogowanym i bez logowania użytkowniku. Po prostu.

wchodzisz na stronę. Na starcie wysyłane jest żadanie ajax do serwera, jako, że pętla spełnia warunek i się wykonuje, dead, strona zawiecha. Zmieniam czas pliku, jeb strona się od razu odblokowuje.


Tylko tak jak pisałem, dla wielu użytkowników ten pomysł ogólnie może być słaby i nie wiem czy w to brnąć, ale z drugiej strony stawianie redisa, czy node i websocetów to mega dużo roboty.
com
https://github.com/panique/php-long-polling zainspiruj sie biggrin.gif
Boshi
no ale wtedy ten warunek nigdy się nie spełni i zwraca co chwilę odpowiedź, bo pierwszy raz masz false czaspliku<0 więc zwraca czas pliku do klienta, a w drugim requeście wysyłasz mu czas pliku, a że czaspliku jest równy czasowipliku to przez zmianę warunku pętla się nie spełni znowu i od razu odpowiedź itd ;p

A co do linku to podobna implementacja jest u mnie biggrin.gif
com. Jakieś inne rozwiązanie dla wielu użytkowników, bo nawet jak rozwiąże ten problem to pozostaje kwestia jak rozpoznawać osobno komunikaty dla każdego zalogowanego użytkownika..
com
tak wiem, dlatego edytowałem wink.gif owszem podobna ale twoja blokuje przeglądarkę, a tamta nie smile.gif
no najlepiej zrobić push z serwera np wykorzystać:
https://www.pubnub.com/tutorial/php-push-api/
lub
https://pusher.com/tutorials/realtime-notifications

lub(nie działą w ie/edge ale jest https://github.com/Yaffle/EventSource)
http://www.howopensource.com/2014/12/intro...er-sent-events/
https://github.com/shahzadthathal/server-se...nts-php-example
https://github.com/licson0729/libSSE-php
nospor
Cytat
Nospor. Sesja tu nic do rzeczy nie ma. Testowane na zalogowanym i bez logowania użytkowniku. Po prostu.

Powiedzialem sesja a nie zalogowany user. Nawet jak nie masz zalogowanego usera to ci symfony startuje sesje. Staraj sie czytac ze zrozumieniem tongue.gif

Cytat
owszem podobna ale twoja blokuje przeglądarkę, a tamta nie
Tamta nie blokuje poniewaz tamta nie uzywa sesji wink.gif
Boshi
Postaram się coś ogarnąć z tego, jak znajdę chwilę czasu, potestuję i dam znać.


Dobra, punkt dla nospora biggrin.gif Jak, żeś Ty na to wpadł? Wyłączyłem sesje przez firewalla

  1. public:
  2. # since anonymous is allowed users will not be forced to login
  3. pattern: ^/.*
  4. security: false


faktycznie działa, nie blokuje strony, ale tak czy siak, muszę mieć załączaną sesję, bo inaczej nie wykonam logowania i ogólnie nic chodzić nie będzie.

Rozwiązanie które podał @com również blokuje żądanie o dziwo.

kto by pomyślał, że stworzenie notyfikacji na stronę internetową jest takie skomplikowane...

@com, nie interesują mnie rozwiązania komercyjne/abonamentowe bo to jest pod inżynierkę. Rozwiązanie może być dowolne, aby działało. Chciałem pominac tylko zwykłego ajaxa odpytującego co sekunde bazę bo to zakrawa o absurd.
A te SSE jakoś tak słabo z dokumentacją.
nospor
Cytat
Dobra, punkt dla nospora biggrin.gif Jak, żeś Ty na to wpadł?
To sie nazywa doswiadczenie tongue.gif

To teraz, jak juz laskawie poslychales sie mnie to mozemy zaczac w koncu rozmawiac.
Masz cos schrzanionego, bo to co probujesz robic to nawet z sesja nie powinno ci blokowac ladowania strony.
Powinno to wygladac tak:
wpierw ladujesz swoja strone a dopiero potem jak juz jest zaladowana do odpalasz swojego ajaxa. Wowczas strona sie normalnie laduje a ajax dziala sobie w tle i niczemu nie wadzi bo strona jest juz zaladowana.

Zas z twojej wypowiedzi wynika, ze twoja strona czeka na zaladowanie dopoki ajax sie nie zaladuje, wiec totalnie cos schrzaniles. wink.gif

Sam robilem cos podobnego, wykorzystywalem long pooling i wszystko ladnie smigalo wg scenariusza ktory ci napisalem powyzej. I dzialalo to rownie dobrze dla jednego usera jak i dla wielu i rzecz jasna byla wlaczona sesja. Wszystko zalezy od kolejnosci, ktora to ewidentnie ty masz zla wink.gif
Boshi
No, ale wygląda to tak jak w pierwszym poście. Zdaje sobie sprawę, że najpierw powinna ładować się strona, potem ajax. Masz może gdzieś ten kawałek kodu u siebie bym porównał?

I jeszcze jedno, jak rozróżnić określonych uzytkowników? bo przewiduje powiadomienia dla wszystkich.. np dodanie jakiejś kategorii oraz powiadomienia indywidualne, np ktoś dostał wiadomość prywatną. Całość działa w oparciu o czas modyfikacji pliku, a wiadomo, że jak zmieni go jedna osoba to powiadomienie poleci do wszystkich.
nospor
To ty pokaz swoj kod a ja porownam wink.gif
maly_swd
A ten ajax nie powinien odpalać się na document.ready?

$(window).ready(function(){ getNewMessage();});
nospor
Powinien. Dlatego prosze go o pokazanie jak on to robi
com
Ostatnio mnie przyćmiło, także sorry biggrin.gif
Boshi
Blokuje żądanie jak je wstawiłeś do symfony?
Sprawdzałem ich demo ale bez sf i nic nie blokowało przeglądarki smile.gif
A i w incognito bez sesji, z kodem js z githuba działa, a w normalnym blokuje się, wiec to może być wina sf wink.gif

O SSE to trochę tam w internecie jest, bez przesady tongue.gif

Co do push z serwera to na potrzeby inżynierki da rade zmieścić się w planie darmowym, a będzie wyglądało bardziej pro tongue.gif
Boshi
@com, pro to raczej lepiej wyglądają własnoręczne rozwiązania które można opisać w pracy a nie "użyłem gotowego płatnego rozwiązania i jest pro tongue.gif"
Też testowałem ich demo i chodziło bez SF, dlatego pisałem, że pewnie sesja.

Skrypt jest ładowany przed końcem body więc nie widzę potrzeby dawanie Ready document.


Wygląda to tak https://gyazo.com/96a7706af2dd7579d5bea1a649bdf14c Jesteśmy na grafiku, klikamy kadrę, dostajemy czerwony błąd, że przerwaliśmy ajaxa i zwiecha. Odblokowuje się po modyfikacji pliku ręcznie.

Być może namieszałem coś w blokach w twigu i np nie ładuje przed końcem body czy coś podobnego, ale teraz mam za duży syf by to wrzucać. Jutro postawię czystą instalkę, wrzucę mój i @com skrypt i przetestuje wtedy. Jak nie ruszy to wrzucę mój syf tongue.gif

@nospor- pytałem wcześniej o możliwość rozróznienia danych użytkowników. Jakiś pomysł w międzyczasie?
com
Boshi ok no owszem, ale czasem nie warto wymyślać koła na nowo, push samemu napisać to by był temat na osobną prace.

Po wyłączeniu sesji tez nie działa ale tylko w normalnym trybie, bo w incognito działa bez zarzutu, wiec najprawdopodobniej jest to kwestia po stronie symfony.
A sprawdzałem na czystej instalacji sf 3.2.1.

No najlepiej żeby rozróżnić to będzie użyć tego sse albo push co mówiłem wink.gif
Boshi
Testowałem na czystej instalce.. każdy skrypt to samo. Próba odświeżenia strony kończy się zawieszeniem i próbą ładowania nowego żądania.

kontroler

http://pastebin.com/GHmVPjeZ

widok
http://pastebin.com/BLvpDvM0

nie ma tu jakiejś filozofii, wg mnie jest w porządku.

@com, rozwiązanie gotowe odpada ze względu, że coś w pracy muszę opisać. SSE mogło by być, ale nie wiem na ile uda mi się implementacja tego.

Swoją drogą, to rozwiązań tego problemu jest masa...

Node + websocety
pooling ajax
long polling ajax
SSE
push (płatny)

Szkoda, że każde oprócz websocetów jest drętwe tongue.gif
com
Pisałem prace inżynierska kiedyś wiec wiem jak to wygląda tongue.gif

Nadal nie rozumiem jaki problem widzisz z SSE:
http://www.w3schools.com/html/html5_serversentevents.asp
Boshi
Denerwuje mnie, że jest tyle rozwiązań i każde jest skomplikowane, ale dobra panowie biggrin.gif

coś ruszyło.

przed uspaniem (czy to skrypt mój czy @com) dodałem $request->getSession()->save(); i o dziwo, ruszyło? nie blokuje sesji, ładuje normalnie wszystko, zmiana w pliku zwraca kolejną notyfikację.. nie zauwazono efektów ubocznych przy ładowaniu tongue.gif

Zostały dwa problemy. Jak teraz porozróżniać użytkowników na postawie tego pliku - lub nie. Jakiś pomysł na algorytm? Tylko tego brakuje i będzie świetnie biggrin.gif
maly_swd
daj w // main loop
while (true) {

file_put_contents('log.log', print_r($_GET, true), FILE_APPEND);

i zobacz co Ci się w tym pliku zapisuje.
Mi to wygląda, że pętla cały czas działa ponieważ ten warunek coś się syfi: if ($last_ajax_call == null || $last_change_in_data_file > $last_ajax_call) {
nospor
Cytat
ale z drugiej strony stawianie redisa, [...] to mega dużo roboty
Ja uzywam docker. Postawienie redisa sprowadza sie do dodania nazwy obrazu z redis. 10 sekund roboty. Wiem, bo tak wlasnie dodalem redis do swojego projektu smile.gif

Cytat
Jak teraz porozróżniać użytkowników na postawie tego pliku - lub nie.
Nie mozesz tworzyc pliku dla kazdego usera z osobna?
Boshi
Cytat(nospor @ 29.12.2016, 17:18:35 ) *
Ja uzywam docker. Postawienie redisa sprowadza sie do dodania nazwy obrazu z redis. 10 sekund roboty. Wiem, bo tak wlasnie dodalem redis do swojego projektu smile.gif

Nie mozesz tworzyc pliku dla kazdego usera z osobna?


Redis odpada ze względu, że muszę to na serwer gdzie nie mam redisa a instlacja jego to 50 zł/rok - dla jednego projektu odpada tongue.gif

Myślałem o tym samym, ale czy to jest optymalne rozwiązanie? pewnie nie, ale z drugiej strony nic innego też mi do głowy nie przechodzi oprócz tego co kiedyś pisałem. Czyli zamiast sprawdzać czas modyfikacji pliku to plik miałby format coś takiego

user 1 czas ostatniej modyfikacji- np prywatna wiadomosc
...

ale tu wychodzą kolejne problemy z obróbką tego itd


Powiedzmy, że co ma działać to jako tako działa. Oparte o user=plik
Tylko zastanawiam się jeszcze jak dodać do tego ogólne notyfikacje- osobny plik admina, ale jak to sprawdzać w serwerze? warunkiem, że jeżeli albo zmienił się czas u danego użytkownika albo u administratora w pliku to wtedy wykonuj to i to?
I jak wykryć zmiane od ostatniej wizyty?

np wchodzę o 13;30 na chwilę i wychodzę. W międzyczasie dostaje powiadomienie. Wchodzę o 13;40 i widzę powiadomienie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.