From polling to long polling - javascript

So I have a script that uses basic polling to show the total amount of records in the database in real time
so nothing complicated so can any one give me an example of my code in a long polling structure. The reason why I ask this question because all the articles on google
search gives me examples in jQuery I cant seem to find a plain JavaScript example that makes sense in my situation. This is a .gif screenshot
of my code in action so you guys know what I mean in detail.
This is my basic polling example code that I need to convert or change into long polling.
index.php
<style>
#label{
margin: 0;
color: red;
font-weight: bold;
}
</style>
<script>
document.addEventListener('DOMContentLoaded',function(){
/**********************************************************************
Check for a new record amount in the data base
**********************************************************************/
function checkForNewRecords(){
var xhr= new XMLHttpRequest();
xhr.onreadystatechange= function(){
if(xhr.readyState == 4){
document.querySelector('#output').innerHTML= xhr.responseText;
}
}
xhr.open('POST','check-for-new-records.php');
xhr.send();
}
setInterval(function(){checkForNewRecords()},1000);
});
</script>
<p id='label'>Total records in the database in real time in basic polling</p>
<div id='output'></div>
check-for-new-records.php
<?php
$db_servername= 'localhost';
$db_username='jd';
$db_password= '1234';
$db_name= 'test';
$db_connect= new mysqli($db_servername,$db_username,$db_password,$db_name);
$db_query= "SELECT COUNT(id) AS id FROM example";
$db_result= $db_connect->query($db_query);
$db_row= $db_result->fetch_object();
$total_records= $db_row->id;
?>
<style>
#total-records{
margin-top: 0;
}
</style>
<p id='total-records'><?php echo $total_records; ?></p>
So how would you guys convert this into long polling and please don't suggest other methods or don't provide an answer that is not helpful i'm only interested in what i'm asking for and i'm pretty sure others are also interested in a plain JavaScript version as well and the reason why I say this is because I
been asking about this topic online for a long time and nobody seems interested in answering this or perhaps they think its too hard to answer this if so why is there so many jQuery examples about this topic and not based on plain JavaScript and not everyone likes to use libraries. I'm just saying I been unsatisfied about the unhelpful answers I been getting from this topic that is based on plain JavaScript, just a heads up.

You should never use setInterval use setTimeout instead.
If you use setTimeout then basic difference for polling and long polling is only where the delay happens. For polling the server will respond immediatly (even if no change happened) and the client will wait n seconds to send the next request. For long polling the server will wait with the respond until new data is available (or a timeout occurs) and the client will immediately send a new request when it gets a response.
There is absolutely no different in implementing it with XMLHttpRequest, fetch or jQuery, the only difference client side is the delay for the next request.
Polling:
function checkForNewRecords() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
document.querySelector('#output').innerHTML = xhr.responseText;
setTimeout(checkForNewRecords, 1000); // polling has the delay on the client
}
}
xhr.open('POST', 'check-for-new-records.php');
xhr.send();
}
checkForNewRecords()
Long-Polling:
function checkForNewRecords() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
document.querySelector('#output').innerHTML = xhr.responseText;
setTimeout(checkForNewRecords, 0);
// long-polling has the delay on the server
// the client initiates a new request immediatly after receiving the response.
}
}
xhr.open('POST', 'check-for-new-records.php');
xhr.send();
}
checkForNewRecords()
On the server side, on the other hand, you usually have to change a couple of things to make long polling work efficiently.
The important differences between polling and long polling that target optimizations, in how to tell the server when to send update informations, but thats completely independent form the method you use to request the data.

Related

How to replace ajax with webrtc data channel

** JAVASCRIPT question **
I'm using regularly ajax via XMLHttpRequest. But in 1 case, I need 1 ajax call per seconds....
but long term wise and with growing number of simultaneous users, it could bloat easily...
I'm reading stuff about webRTC data channel and it seems interesting and promissing.
Here my working AJAX function as an example of how easy and there is a few lines of codes to communicate from the browser to the server and vice-versa
function xhrAJAX ( divID , param2 ) {
// random value for each call to avoid cache
var pcache = (Math.floor(Math.random() * 100000000) + 1);
// parameters
var params = "divID="+encodeURIComponent(divID)+"&param2="+encodeURIComponent(param2);
// setup XMLHttpRequest with pcache
var xhr = new XMLHttpRequest();
xhr.open("POST", "/file.php?pcache="+pcache, true);
// setup headers
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// prepare onready scripts
xhr.onreadystatechange = function(e) { if (xhr.readyState == 4) { $("#"+divID).html(e.currentTarget.responseText) ; } }
// send the ajax call
xhr.send(params);
}
How can I "transpose" or "convert" this ajax workflow into a webRTC data channel ? in order to avoid to setup a setInterval 1000...
Note: I mean how to replace the javascript portion of the code. PHP here is only to illustrate, I don't want to do a webRTC via PHP...
Is there a simple few lines of code way to push/receive data like this ajax function ?
the answer I'm looking for is more like a simple function to push and receive
(once the connection with STUN, ICE, TURN is established and working...)
If I need to include a javascript library like jquery or the equivalent for webRTC, I'm welcoming good and simple solution.
*** The main goal is this kind of scenario :
I have a webapp : users in desktop and users within webview in Android and IOS
right now I have this workflow => ajax every 3 seconds to "tell" the main database that the user is still active and using the browser (or the app)
But I'd like to replace with this kind : when the user uses the browser => do a webrtc data chata in background between the browser and the server
While reading on the web I think that webRTC is a better solution than websocket.
** I did a bit of search and found peerjs....
https://github.com/jmcker/Peer-to-Peer-Cue-System/blob/main/send.html
I'll do some testing, but in the meantime, if someone can trow ideas, it could be fun.
Cheers

Continuous DB calls with AJAX in straight JS

This is my first question here so I will start by saying: Hello to everyone!
I am trying to make a live data "presentation" in the form of a fancy table using straight JavaScript and Ajax, backend is PHP. In order to refresh the table I need to make requests at every, lets say 3 seconds, 4 is ok to. The database is RedisDB. I made the php script to fetch the data and its ok. I made a single JS file to request and handle/process the data and it's sort of ok.
The presentation looks great and the algorithm that is written in JS works excellent, it's about 600 lines, some simple if-else's and switches other a little more complex.
It now gets nasty. I can't get the freaking thing to do this continuously, I tried ways with setTimeout() and setInterval(), I made timers and infinite loops with sleep-like functions and so on, but it just can't survive that next request after the initial when the page loads.
The code for Ajax request is pretty straightforward for pure JS. I get my JSON string data parse it with jsonParse() and then do my processing of the data.
This all works, it's the next request that fails, no matter how it's initiated (user action or something else).
AJAX code:
window.onload = function(){
getEventdataFromDB();
}
function getEventdataFromDB(){
var xmlhttp;
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
var dbData = xmlhttp.responseText;
if(dbData != ''){
processEvents(dbData); //function for data processing
}
}
}
xmlhttp.open('GET','getEvents.php?dataRequest=true',true);
xmlhttp.send();
}
I know that it's a bit of a sin these days not to follow the flow and use jQuery and other frameworks but I'm just not big on the latest and greatest simplification of stuff that works just fine, to begin with.
What is the best way to do this, how should I proceed, what to use. I did some researched and things point to chaining callbacks and Promise objects.
There is obviously no way that I am the first one to do this so what is the way forward here.
The only way to ensure the previous request is over before starting the next one is so start the next call from the onreadystatechanged event of the previous one. Because ajax runs asynchronously, there's no guarantee whether any other code you run will execute before or after the ajax call finishes.
So you need to re-organise your script a bit:
var xmlhttp;
window.onload = function(){
setupAjaxObject();
getEventdataFromDB();
}
function setupAjaxObject()
{
if(window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
}else{
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
var dbData = xmlhttp.responseText;
if(dbData != ''){
processEvents(dbData); //function for data processing
}
}
getEventdataFromDB(); //run the next request
}
}
}
function getEventdataFromDB(){
xmlhttp.open('GET','getEvents.php?dataRequest=true',true);
xmlhttp.send();
}
If you wanted a little delay between the requests, you could wrap the call to the next request inside a timeout.

Ajax & JavaScript | Limiting requests triggered by user

I am currently playing around with some Ajax code. I have come up with this scenario to try and mirror my problem to see if you, experts, can present a solution, thanks.
Scenario:
I have a HTML button like so: <p onclick="ajax_call();">Click</p>. Upon clicking this button it will launch an AJAX request to a php page like this:
function ajax_launch(){
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = ajax_launch_callback;
xmlhttp.open("POST", "/php_script", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send();
}
function ajax_launch_callback(){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
// code to do something once response is here successfulyl
}
}
This then does some PHP code in the php_script file and returns an $output
Issue:
The php_script page that is called via AJAX is quiet heavy and makes several API and database calls making the page "slow" to load (which is perfectly fine). However at the moment, whilst the page is waiting for a response (it is still doing the php and not yet returned anything) a user can technically spam the button to launch many ajax calls. Ideally, this will just produce stress on the server and I need a way that once the request is pending and not come back, you cannot make further requests.
How can i achieve something like this?
Thanks in advance, looking forward for your solutions/consultation
ALSO:
By multiple requests, this is what i mean - see picture of when i spam click the button to launch several requests whilst the first one isn't done (not returned anything yet):
Image of chrome debugger (networks tab)
Although the mentioned javascript solutions here and in the linked question are a nice addition, you should really do this server-side as a spammer would not necessarily be using a browser and / or could have javascript disabled.
If you use sessions on the server, the session will be locked when a request is being processed so you will only process one request per user at a time. However, requests could queue up (that is perhaps what is showing in your networks tab data?) so you could complement that with a rate limit on for example the IP address.
You can try this:
var xmlhttp;
function ajax_launch() {
if (xmlhttp && xmlhttp.readyState == 4 || !xmlhttp) {
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = ajax_launch_callback;
xmlhttp.open("POST", "/php_script", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send();
}
}
function ajax_launch_callback() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// code to do something once response is here successfulyl
}
}
This things might be helpful:
Add this HTML
<div style="display: none;" id="screenblocker"> </div>
And this styles:
#screenblocker {
position:absolute;
left:0px;
top:0px;
right:0px;
bottom:0px;
background-color:#ffffff;
opacity:0.4;
filter:alpha(opacity=40);
z-index:9999999;
}
And script part:After the AJAX call
var e = document.getElementById('screenblocker');
if (e != null) {
e.style.display = 'block';
setTimeout("document.getElementById('screenblocker').style.display = 'none';", 5000);//considering 5 seconds to load, you can block longer if needed
}
And on AJAX success:
document.getElementById('screenblocker').style.display = 'none';

How to interactively get data from php script using javascript

I have this php script:
<?php
$arr = array(array("a","b"),array("c","d"));
qq($arr);
function qq($arr){
foreach($arr as $ar => $r){
//getting some work done
//sending the array $r (or values)to javascript
}
}
?>
Is it possible to get the value of 0 array using javascript before array 1.
what i get so far is this js from stackoverflow:
<script type="text/javascript">
function q(){
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "http://127.0.0.0.1/q.php");
xmlhttp.send(null);
xmlhttp.onreadystatechange = callbackFunction;
function callbackFunction(){
if (xmlhttp.readyState == 4){
xml = xmlhttp.responseText;
document.getElementById("q").value = xml;
}}}
</script>
but it's not doing what i want(i think i'm missing something).
my html:
<input type="submit" onclick="q();" />
<div id="q"></div>
<div id="q1"></div>
Is it possible to put array 0 value in div(id=q) and when array 1 is ready put it's value in div(id=q1)
The "normal" HTTP Requests via XMLHttpRequest() do not allow such behaviour in a single request.
You have the following options instead:
Server Send Events
upside
They are incredibly easy to build. Nothing really special is needed on the server. Just google for server sent events and you'll find some examples on how they work.
They go through proxys and firewalls just as well as any other http request, because it is a normal http request.
downside
Does not run on Internet Explorer (?)
May fail to update in realtime if a proxy somewhere buffers too much. However in this case it still works, it just misses the realtime communication
Websockets
upside
Works in all recent browsers. Enables you to do full duplex communication and gets everything right that you need.
downside
May or may not work through proxies depending on their configuration.
Special extensions are needed on the server
(Long-) polling
upside
Best compatibility (works even in older browsers, no issues with proxies or firewalls)
downside
Creates lots of overhead because it does create for each message a new http connection
You need to store intermediate results somewhere because the poll requests come in different threads to your application than your code generation mechanism.
can you try with
if (xmlhttp.readyState == 4){
xml = xmlhttp.responseText;
document.getElementById('q').innerHTML=xml;
}}}

Not Receiving Asynchronous AJAX Requests When Sent Rapidly

My script is sending a GET request to a page (http://example.org/getlisting/) and the page, in turn, responds back with a JSON object. ({"success":true, "listingid":"123456"})
Here's an example snippet:
var listingAjax = new XMLHttpRequest();
listingAjax.addEventListener("load", listingCallback, false);
function listingCallback(event) {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
}
listingAjax.open("GET", "http://example.org/getlisting/", true);
listingAjax.send();
Simple enough. The script works perfectly too! The issue arises when I want to do this:
var listingAjax = new XMLHttpRequest();
listingAjax.addEventListener("load", listingCallback, false);
function listingCallback(event) {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
}
window.setInterval(function() {
listingAjax.open("GET", "http://example.org/getlisting/", true);
listingAjax.send();
}, 250);
What I imagine should happen is my script would create a steady flow of GET requests that get sent out to the server and then the server responds to each one. Then, my script will receive the server's responses and send them to the callback.
To be more exact, say I let this script run for 5 seconds and my script sent out 20 GET requests to the server in that time. I would expect that my callback (listingCallback) would be called 20 times as well.
The issue is, it isn't. It almost seems that, if I sent out two GET requests before I received a response from the server, then the response is ignored or discarded.
What am I doing wrong/misunderstanding from this?
Many browsers have a built in maximum number of open HTTP connections per server. You might be hitting that wall?
Here is an example from Mozilla but most browsers should have something like this built in: http://kb.mozillazine.org/Network.http.max-connections-per-server
An earlier question regarding Chrome:
Increasing Google Chrome's max-connections-per-server limit to more than 6
If you have Windows, take a look at a tool like Fiddler - you might be able to see if all of the requests are actually being issued or if the browser is queueing/killing some of them.
You can't reuse the same XMLHttpRequest object opening a new connection while one is in progress, otherwise it will cause an abrupt abortion (tested in Chrome). Using a new XMLHttpRequest object for each call will solve that:
function listingCallback(event) {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
}
window.setInterval(function() {
var listingAjax = new XMLHttpRequest();
listingAjax.addEventListener("load", listingCallback, false);
listingAjax.open("GET", "http://example.org/getlisting/", true);
listingAjax.send();
}, 250);
This will work nicely queueing a new ajax request for each interval.
Fiddle
Note that too frequent calls may cause slowdown due to the maximum limit of concurrent ajax calls which is inherent to each browser.
Though, modern browsers have a pretty fair limit and very good parallelism, so as long as you're fetching just a small JSON object modern browsers should be able to keep up even when using a dial-up.
Last time I made an ajax polling script, I'd start a new request in the success handler of the previous request instead of using an interval, in order to minimize ajax calls. Not sure if this logic is applicable to your app though.

Categories

Resources