Link to home
Start Free TrialLog in
Avatar of J N
J N

asked on

Long polling

Hi,

I am having some problems with long polling working on one of my projects.

i created this long polling function (it is a mix of jquery and js im going to change this)
//LONG POLLING
function messages_longpolling( timestamp, last_id, id){
   var t;
 
   if( typeof last_id == 'undefined' ){
      last_id = 0;
   }
 
   $.ajax({
      url: 'ajax/messages_main.php?message_id=' + id + '&timestamp=' + timestamp + '&last_id=' + last_id, 
      type: 'POST',
      dataType: 'json',
      success: function( payload ){
         clearInterval( t );
         if( payload.status == 'results' || payload.status == 'no-results' ){
            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id                         );
            }, 1000 );
            if( payload.status == 'results' ){
				//UPDATE CONTENT
  					document.getElementById('message_thread').innerHTML=payload.content;
					document.getElementById('show_msg_form').style.display='block';
					
					//MAKE SURE THERE IS A SUBJECT AND IT IS NOT EMPTY
					if(payload.subject){
						//CHANGE HEADER TO SUBJECT
						document.getElementById('users_name_heading').innerHTML='Group Message: ' + payload.subject;
						
					}else{
						//DEFAULT SHOW NAMES
						document.getElementById('users_name_heading').innerHTML=payload.heading;
					}
					
					//EDIT FORM VALUES
					document.getElementById('msg_id').value =payload.msg_id; 	
					document.getElementById('msg_indi').value =payload.msg_indi; 	
					document.getElementById('msg_sub').value =payload.msg_sub; 
							
					//ADJUST THE SIDE PANEL SETTINGS
					var badge =document.getElementById('msg_badge'+id).innerHTML;
					if( badge =='unread'){
						document.getElementById('msg_badge'+id).innerHTML =payload.badge; 
					}
					//GO TO BOTTOM
					var div =document.getElementById('chat-content');
					div.scrollTop= div.scrollHeight;
					
					//STOP PROPIGRATION
					//a.stopPropagation();
					//a.cancelBubble = true	
                  
            }
         } else if( payload.status == 'error' ){
			 //THERE WAS AN ERROR 
			 alert('Ooops! Something has gone wrong. Please try again!'); 
			 
         }
      },
      error: function(payload){
         clearInterval( t );
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id );
         }, 15000 );
      }
   });
}

Open in new window


i then use an inline on click event to trigger the function like so
<a href="#" class="active" id="msg3" onclick="messages_longpolling( 1406321552,'',3); return false">  

Open in new window


the ajax code fires once someone has clicked one of the chats (there a different chats)

The ajax request gets the information using the following code

function get_all_messages($sql, $array){
	//SET THE GLOBALS
	global $conn;
	
	//SETUP SOME STANDARD VARS
	$messages='';
	$heading='';
	$all_senders='';
	$count=0;
	$dir=$_SERVER['SERVER_NAME'].'/profile/images/profile_pics/'; //profile directory path
	$timestamp = (int) trim( $_GET['timestamp'] );
	$last_id = isset( $_GET['last_id'] ) && !empty( $_GET['last_id'] ) ? $_GET['last_id'] : 0;
	$time_wasted = 0;
	$last_id = '';	
	$data=array();
		
	//PREPARE SQL
	$prep=$conn->prepare($sql);
	$ex=$prep->execute($array);
	
	//CHECK IF THERE ARE ZERO ENTRIES
	$num = $prep->rowCount();
	if($num <=0){
		//CHANGE HEADING
		$heading='<li class="conversation-divider"><span>* No Messages * </span></li>';
		
		//PERFORM SOME CHECKS
		while($num <=0){
			if($num <=0){
				if($time_wasted>=60){
					//CREATE JSON ARRAY
					$data=array(
						"status"=>"no results", 
						"timestamp"=>time(),
						"last_id"=>0, 
					);
				}
				
				//SLOW DOWN PROCESS TO LIMIT SYSTEM RESOURCES
				sleep(1);
				
				//CHECK MESSAGES AGAIN
				$ex=$prep->execute($array);
				$num = $prep->rowCount();
				$time_wasted++;
			}
		}
	
	//EXECUTE REMAINING FUNCTIONS IF TEST PASSES
	}else{
		
		//THERE ARE NEW MESSAGES
		if($num>=1){
			//GET NEW MESSAGES
			
			//SETUP THE SQL FOR GETTING PEOPLE INFORMATION
			$ppl='SELECT user_nickname, avatar FROM bb_users WHERE username=(:user) LIMIT 1';
			$ppl_prep=$conn->prepare($ppl);
	
			while($fetch= $prep->fetch(PDO::FETCH_ASSOC)){
				//SETUP VARS
				$id=isset($fetch['id'])?$fetch['id']:'';	
				$original_id=isset($fetch['original_id'])?$fetch['original_id']:'';	
				$composed_date=isset($fetch['composed_date'])?date("F j Y, g:i a",strtotime($fetch['composed_date'])):'';
				$sender=isset($fetch['sender'])?$fetch['sender']:'';
				$recipient=isset($fetch['recipient'])?$fetch['recipient']:'';
				$subject=isset($fetch['subject'])?$fetch['subject']:'';
				$message=isset($fetch['message'])?$fetch['message']:'';
				$heading=' <li class="conversation-divider"><span>Conversation started at '.$composed_date.'</span></li>';
				$individuals=isset($fetch['individuals'])?$fetch['individuals']:'';
				$avatar=$_SESSION['avatar'];
				$nickname=$_SESSION['user_nickname'];
				$sent_class='sent';
						
				//TEST TO SEE IF SENDER AND RECIPIENT ARE EQUAL
				if(($sender !== $recipient)){
					//THE USER VIEWING IS NOT THE SENDER
					$ppl_array=array(":user"=> $sender);
					$ppl_ex=$ppl_prep->execute($ppl_array);
					
					//GET THE DATA
					if($person = $ppl_prep->fetch(PDO::FETCH_ASSOC)){
						$avatar=$person['avatar'];
						$nickname=$person['user_nickname'];
						$sent_class='receive';
						
						//GET ALL RECIPIENTS
						$all_senders[]=$nickname;
					}
				}	
				
				//CREATE THE START OF THE MESSAGE
				if($count==0){
					//ADD HEADER TO START OF MESSAGE THREAD
					$messages.=$heading;
					
				}elseif($count % 20 ==0){
					//ADD THE DATE OF THE TENTH POST
					$sub_date=date("F Y", strtotime($composed_date));
					$messages.='<li class="conversation-divider"><span>'.$sub_date.'</span></li>';
				}
				
				//DISPLAY TO CONTENT
				$messages.='
					<li class="message '.$sent_class.'">
					  <div class="media">
						<div class="pull-left user-avatar">
						  <img class="media-object img-circle" src="//'.$dir.$avatar.'">
						</div>
						<div class="media-body">
						  <p class="media-heading"><a href="#">'.ucwords($nickname).'</a> <span class="time">'.$composed_date.'</span></p>
						  '.$message.'
						</div>
					  </div>
					</li>
							
				';
						
				//INCREASE COUNT
				$count++;	
				
			}
			
			//CONVERT ALL_SENDERS INTO A STRING
			if(is_array($all_senders)){
				//REMOVE DUPLICATES
				$all_senders=array_unique($all_senders);
					
				//CONVERT TO STING
				$all_senders= implode(", ",$all_senders);
			
			}
			
			//SETUP ARRAY
			$data=array(
				'status'=> 'results',
				'timestamp'=>time(),
				'last_id'=>$id,
				'heading'=> ucwords($all_senders),
				'subject' => $subject,
				'content'=> $messages,
				'badge'=>'',
				'msg_id'=> $original_id,
				'msg_indi'=> $individuals,
				'msg_sub'=> $subject,
			);
			
		}

	}
	
	//JSON ENCODE
	$data=json_encode($data);
	
	//DISPLAY DATA
	die( $data);
}

Open in new window


declared in messages_main.php
       $sql='SELECT * FROM messages WHERE original_id=(:msg_id) AND recipient=(:user) AND composed_date>=(:time) ORDER BY id ASC LIMIT 100';
	$array=array(":msg_id"=>$ID, ":user"=>$_SESSION['username'], ":time"=>time());
	get_all_messages($sql, $array);

Open in new window



since using the code my project takes considerably longer to load. and im not getting a "real" time response

When i let my page site and wait and pull up google console i get the following errrors

http://www.bushbrigade.com/bushbase/system/ajax/messages_main.php?message_id=undefined×tamp=undefined&last_id=0 
where have i gone wrong and what can i do to make this work?

if you would like to see a working example it can be found here

http://www.bushbrigade.com/bushbase/system/messages.php

user: expert-exchange
pass: 3XP3rt!!!!

thanks

Jayme
Avatar of Gary
Gary
Flag of Ireland image

Login not working and is this link where the problem is?
Avatar of J N
J N

ASKER

Hi,

looks like someone change the password i have changed it back and it works now



Yes the link is the page i would i am using.
Here you are not passing the msg.id - should you be?

            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id                         );
            }, 1000 );

Open in new window

Avatar of J N

ASKER

Yea I noticed that too

I adjusted that to include payload.msg_I'd

Still really slow and no response
 And get the undefined for message_id
In the error function of your ajax call you are rerunning the ajax call but you have invalid values which ends up in a continual loop with errors.

      error: function(payload){
         clearInterval( t );
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id, payload.msg_id );
         }, 15000 );

Open in new window

Avatar of J N

ASKER

So what should I adjust it too mine looks just like the one u just posted. I still have funny stuff happening
That is your code, I was pointing out where the problem is.
As to what to do - I'm not sure as I haven't figured out your logic flow yet but I would guess you have some default values there that it can fall back to if there is an error
No points for this please.  I don't want to rain on anyone's parade, but PHP is really built for HTTP client/server work in a RESTful environment.  The requests are atomic, complete and stateless and the responses are complete and usually instantaneous.  If you're using Apache It may be the wrong tool for a long-polling application, since the Apache threads can be eaten up pretty quickly.  

These seem to be built for long-polling:
http://www.tornadoweb.org/en/stable/
http://cometdproject.dojotoolkit.org/

I don't know what a good PHP answer might be.
ASKER CERTIFIED SOLUTION
Avatar of Gary
Gary
Flag of Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of J N

ASKER

Hi,

i have considered using node.js however i would need to switch my server and im not interested in doing this right now.

the app im building is small so i would like to keep php

ive updated my js however im not getting my desired results

//LONG POLLING
function messages_longpolling( timestamp, last_id, msg_id){
   var t;
 
   if( typeof last_id == 'undefined' ){
      last_id = 0;
   }
 
   $.ajax({
      url: 'ajax/messages_main.php?message_id=' + msg_id + '&timestamp=' + timestamp + '&last_id=' + last_id, 
      type: 'GET',
      dataType: 'json',
      success: function( payload ){
         clearInterval( t );
         if( payload.status == 'results' || payload.status == 'no-results' ){
            t=setTimeout( function(){
               messages_longpolling( payload.timestamp, payload.last_id , payload.msg_id);
            }, 1000 );
            if( payload.status == 'results' ){
		 //UPDATE CONTENT
  					
                  
            }
      },
      error: function(payload){
         clearInterval( t );
		 alert('error');
         t=setTimeout( function(){
            messages_longpolling( payload.timestamp, payload.last_id, payload.msg_id );
		  
         }, 15000 );
      }
   });
}

Open in new window


i didnt make the code i got it from a website and then adapted it to my stuff. im not really sure how i can change it to get the desired output. the one big item is that my app has multiple chats and not one large one.

the website i used is http://webcooker.net/ajax-polling-requests-php-jquery/