?
Solved

Long polling

Posted on 2014-07-25
10
Medium Priority
?
245 Views
Last Modified: 2014-07-28
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
0
Comment
Question by:M. Jayme Nagy
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 58

Expert Comment

by:Gary
ID: 40220491
Login not working and is this link where the problem is?
0
 
LVL 6

Author Comment

by:M. Jayme Nagy
ID: 40220529
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.
0
 
LVL 58

Expert Comment

by:Gary
ID: 40220573
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

0
Get real performance insights from real users

Key features:
- Total Pages Views and Load times
- Top Pages Viewed and Load Times
- Real Time Site Page Build Performance
- Users’ Browser and Platform Performance
- Geographic User Breakdown
- And more

 
LVL 6

Author Comment

by:M. Jayme Nagy
ID: 40220593
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
0
 
LVL 58

Expert Comment

by:Gary
ID: 40220611
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

0
 
LVL 6

Author Comment

by:M. Jayme Nagy
ID: 40220632
So what should I adjust it too mine looks just like the one u just posted. I still have funny stuff happening
0
 
LVL 58

Expert Comment

by:Gary
ID: 40220639
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
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 40220682
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.
0
 
LVL 58

Accepted Solution

by:
Gary earned 2000 total points
ID: 40221915
Ray is right - Apache is not built for this.
You may want to look at nGinx or node.js for handling your long polling - both are single threaded and can easily handle thousands of concurrent connections without belching.
If you know js then using node.js will be relatively easy
nGinx requires a bit more hands on work

I personally use nGinx and after the initial 'How the hell do you do...' its pretty easy to get on with.
0
 
LVL 6

Author Comment

by:M. Jayme Nagy
ID: 40223414
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/
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Build an array called $myWeek which will hold the array elements Today, Yesterday and then builds up the rest of the week by the name of the day going back 1 week.   (CODE) (CODE) Then you just need to pass your date to the function. If i…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
Suggested Courses

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question