From scratch this question did not arise, using the function

$(window).unload(function(){ $.post( 'do.php', { user: $name, status: 'off' } ); }); 

I do a post to the file do.php, which in turn updates the status of the user in the database, it was "on", it became "off", it all just looks pretty, but! Where do without "but"? It does not work !!! And if it works, then after three at best.

The question is how to make a more precise definition when the user closed the site (window / browser)?

    6 answers 6

    The problem is that since jQuery's ajax requests are asynchronous by default, when you send such a request on the unload event, it simply does not have time to execute. As soon as the handler returns, the browser immediately closes the tab without waiting for the execution of any ajax requests.

    To guarantee the execution of ajax, you must send a request synchronously:

     $.ajax('do.php', {async: false, data: { user: $name, status: 'off' }}); 

    In this case, the $.ajax will be blocked until a response from the server comes.

    • @Ilya Pirogov - the thought is right, but even that will not save the lights from being turned off :) - Zowie
    • one
      Of course, timeout will save you from turning off the light. But> I can not wait 10-15 minutes, I need so that if the user is gone, then all this is immediately noticed, as in chat rooms. This will solve in 99.9% of cases. What can not be done by timeout alone. - Ilya Pirogov
    • @Ilya Pirogov, it is better to send this request asynchronously. For the page to be closed, receiving a response from the server is no longer important. And, here on the server, the exit signal will go offline. The main thing is that the server script should work to the end regardless of the fact that the client has disconnected ( ignore_user_abort() ). - KiTE 4:05 pm
    • one
      @KiTE, there is no guarantee that at least the request will have time to leave. This can only guarantee a synchronous request. And that would not wait until the request is processed, it is better to use fastcgi_finish_request() . - Ilya Pirogov

    Here you need a comprehensive solution. As @sercxjo correctly noted, the processing of leaving the site is not a panacea.

    When the page has loaded, we start the timer, which at certain intervals Ajax sends to the server the presence information. The server, in turn, receives the request and records the time of the last access. Further, to find out if the user is present or not, it is enough for the server to calculate the interval between the time of the last call by timer and the current moment. If this interval exceeds the interval of the client timer, then Ajax requests from the browser no longer arrive and the user is gone.

    The more often the browser will send such requests, the more accurate the server will know about who is present and who is not. But, at the same time, frequent calls increase the load on the server. Therefore, the optimal polling interval should be calculated on the basis of the estimated number of online users, the computing power of the server and common sense. For example, why pull a server every 5 seconds if 2-5 minutes is not critical. Calculation type: 100 онлайн-пользователей / интервал в 5 сек. = дают среднюю нагрузку 20 запросов в секунду 100 онлайн-пользователей / интервал в 5 сек. = дают среднюю нагрузку 20 запросов в секунду .

    Plus, the processing of leaving the page, you can hang up sending Ajax-request with the information that the user has left. If this event works, then the server will know the exact moment of departure.

    With a large number of visits with information about the presence is worth thinking about how to store this information on the server. To prevent each request from pulling the server screws each time, you can use memcached or a MySQL table with HEAP type. The peculiarity of HEAP-tables is that they keep their contents in the operative and do not write it on a screw, and this is quite enough for information on the presence of it.

    Something like this...

    UPD: If you develop the idea further, then you can work out the system with automatic load balancing on the server. For example, in a server script we sew a constant: process no more than 20 requests per second. Then, in response to the Ajax request from the client, you can send him the recommended interval for the next call from him. The server knows the current number of online clients (for example, 300 pcs.), The server knows the constant of 20 requests per second. At the time of the next request from the client, a simple calculation of 300 шт. / 20 = 15 сек. 300 шт. / 20 = 15 сек. and these 15 sec. sent to the customer. And the client, having received the answer, writes this recommended interval into his timer until the next call.

    Thus, at peak times, the server itself will regulate the number of requests sent with the presence information.

      Store in the database the time the user last accessed the site. The message about closing the page may never come if the computer freezes, the network disappears, the laptop goes into hibernation ...

        It is possible so:

         $(window).bind('beforeunload', function () { //тут уведомляем сервер об уходе пользователя удобным нам способом }); 

        It works on closing the page, moving to another page. Does not work in opera.

          Indeed, using JS is better not to do this. The situations can be different: starting from the fact that the user is "stuck" and to the point that the "smart" user has disabled JavaScript in his browser. This is a responsible business, which means that the user (and therefore JSʻu) cannot be trusted in any way! PHP (or any other server language) works well here. In this case, the user pinging algorithm is simple: data is entered that the user is online, then every 10-15 minutes it is checked whether the user has updated the page, if not, in 99% of cases the user has already logged out (or “hung”, like it's called)

          • 2
            @Asen, calmly all this is done on JS, what is the problem with security, what can a user do? - Oleg Arkhipov
          • one
            @Construct - yes? The users have JS enabled, half of Moscow is sitting in your chat room and nobody else, let's say everyone has turned the lights on. Your application will claim that a lot of people are online, when in practice - online will be = 0. Now we develop a thought - let's say this happened 5 times during the week during the month :) What is the point of writing logic then? You can stupidly do echo mt_rand (100, 100500). "users online"; The main work in any case should be done by the server - Zowie
          • 2
            @AlexWindHope, and how will CRON help? CRON works on the server side. How does the server know who is online, and who does not, if the clients do not specifically inform the server about this? In this case, the latest current client states are those that the server can record at the time of issuing the page to each browser. - KiTE
          • one
            @AlexWindHope, I fully support! --- @Construct, the answer to my sixth comment was also in my answer, but thanks to @AlexWindHope, who poked his nose at the right place) - AseN
          • 3
            @AlexWindHope, well, well, since you offer such a super-option, cut its essence in the answer. And, at the same time, tell me how you will determine the fallen off customers knowing only online=1 . No, of course you can, of course, use the next iteration of the krone to extinguish all those who have online=1 without paying attention to the fact that one loaded the page two minutes ago and the other one second ago. . And there, tell me for whom your CRON will regularly jerk the scripts during periods of zero site traffic.> A server is definitely needed for an adequate solution of this task. LOL, who would talk about the captain. - KiTE 4:41 pm

          Collect all events events in a heap, spread by executable files and hang all the files on kroner without any Ajax.