0

Scenario: I have a Message page which contains a container whose left section contains contacts and groups to send message and right one has conversation flow. The conversation flow is loaded via ajax while on other hand clicking on any contact or group.this is what it looks like will load the contents on the right side using a javascript file which contains a setinterval function that executes every 5 seconds to check the database for new messages and grabs that message for displaying it in the conversation div.

Problem: on first load of the page, when i click a contact or group, obviously the content is loaded and the setinterval function runs right away. when i click another contact or group, loads the content again and executes the setinterval function again, problem is that there are now two setinterval function running when you try to look at the chrome developer tools. As you can see in this image, there are two requests now, 1 for contact and 1 for group since i clicked a contact and a group. And the requests keeps adding up upon clicking more contacts and groups.

This is the code for loading content via ajax when clicking on a contact or group:

$('.my_contacts a.list-group-item,.my_groups a.list-group-item,.new_message .list-group-item a').click(function(){
        var href=$(this).attr('href');
        $('.list-group-item').removeClass('active');
        $(this).addClass('active');
        $.ajax({
            url:href,type:'post'
        }).done(function(d){
            $('#center-wing').html(d);
        });
        return false;
    });

And this is the content inside the loaded ajax data:

...more html content here
<script>
$(function(){
    $.getScript("res/js/custom/in-page/message.js");
});
</script>

And this is the code the runs every 5 seconds in message.js:

if(notification == true){
        checkNewMsgId=setInterval(function(){
            $.ajax({
                url:'message/check_new_message/' + recipient + '/' + type,
                type:'post'
            }).done(function(d){
                if(d.length > 0){
                    var obj={};
                    lastmsg.addClass('hide');
                    reset_inactivity();
                    for(var o in d){
                        var date=new Date(d[o].SentDate),time=format_time(date);

                        bubble_tpl_left.find('.bubble').attr('data-pk',d[o].Remarks);

                        if(d[o].SenderId == recipient){
                            lastmessagedate=format_date(date);
                            lastmessagetime=time;
                        }

                        if(type == 'CustomGroup') bubble_tpl_left.find('.msg_sender').removeClass('hide').html(d[o].FirstName + " " + d[o].LastName);

                        send(d[o].Reply,time,bubble_tpl_left);

                        obj.title=name;
                        obj.body=d[o].Reply;
                    }
                    if(pagehidden == true){
                        ding.play();push_notify(obj);
                    }else blop.play();
                }
            });
        },5000);
    }

...Sorry for the long post guys. Im really stuck at this one, ive tried clearing the interval before executing the setinterval.

Help will be much appreciated guys :)

Chetan Kumar
  • 1,331
  • 1
  • 10
  • 16
Mykel Aballe
  • 235
  • 1
  • 4
  • 15

2 Answers2

1

(1) Have two functions. One that loads a conversation for a group (loadConversion()), and one that updates the messages for a conversation (updateMessages()).

(2) Call loadConversion() when the user clicks on a group. When that ajax call returns, it should call setTimeout() (not setInterval()) to execute updateMessages() after a 5 second wait. When the ajax call in updateMessages() returns, it will call setTimeout() again to call updateMessages() after a 5 second wait. This sets up the continuous update.

(3) But when the user clicks on a group, you need to cancel any existing timer and abort any outstanding ajax calls before calling loadConversion(). (Or you could do this inside loadConversion() before making the next ajax call.)


The setTimeout() function returns a timerId. Store that in a variable. You can then pass it to clearTimout() to cancel the timer.

Likewise, the $.ajax() function returns a jqXHR object, which can be used to abort the ajax call.

John S
  • 21,212
  • 8
  • 46
  • 56
0

Think of the entire page as one page, and each separate area as just a section of the page -- not as a new document.

Do not load your javascript with the page you are loading for the right-side section. The javascript should be part of the main document, not part of that section. You are getting multiple intervals because every time you reload that part of the page, you are running that js and starting a new setInterval -- which continues running.

Use a hidden input field to store the href of the presently selected contact, and have your repeating AJAX code block send that href to the PHP file that requests/returns new messages from the DB.

/* javascript/jQuery: */

$('.my_contacts a.list-group-item,.my_groups a.list-group-item,.new_message .list-group-item a').click(function(){
    var href=$(this).attr('href');
    $('#curr_href').val(href); //store current href
    $('.list-group-item').removeClass('active');
    $(this).addClass('active');
    $.ajax({
        type: 'post',
         url: href
    }).done(function(d){
        $('#center-wing').html(d);
    });
    return false;
});
<!-- HTML: -->

    <!-- stick it down at bottom of body, like so -->
    <input type="hidden" id="curr_href" />
  </body>
</html>

Your repeating AJAX -- which should be part of the main document, not loading with the chat history -- can do something like this:

var href = $('#curr_href').val();
$.ajax({
    type:'post',
     url: href
}).done(function(d){
  //etc etc etc

In this use case, you also should look carefully at using a recursive setTimeout as opposed to a setInterval:

http://www.erichynds.com/blog/a-recursive-settimeout-pattern

setTimeout or setInterval?

Community
  • 1
  • 1
cssyphus
  • 37,875
  • 18
  • 96
  • 111
  • i havent applied your solution yet but i transferred the script tag from the loaded section to the main document. so in the code likes like this now: `$.ajax({ url:href,type:'post' }).done(function(d){ $('#center-wing').html(d); $.getScript("res/js/custom/in-page/message.js"); }); return false;` – Mykel Aballe Jun 25 '16 at 04:37
  • still doesnt work.multiple requests are still running in the background. it seems the loaded script in the ajax callback is retained. is there a way to remove that script running in the background somehow? – Mykel Aballe Jun 25 '16 at 04:45