Ajax & JavaScript | Limiting requests triggered by user - javascript

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';

Related

Adblocker blocks XMLHttpRequest

I understand the fact, that adblockers try to deny loading (image) data later on. Anyway, I want to send some data to a php script (/log.php) to save it in a sql database. So in fact I don't care about the responsetext. This is my current js function I use to call the php script:
function log(id, unix_ms, frameid, eventtype, targetid, value){
var parameters = "";
parameters = parameters.concat("id=", encodeURI(id), "&unix_ms=", encodeURI(unix_ms), "&frameid=", encodeURI(frameid), "&eventtype=", eventtype, "&targetid=", targetid, "&value=", value);
var httprequest = new XMLHttpRequest();
httprequest.open("POST", "/scripts/log.php", true);
httprequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
httprequest.onreadystatechange = function() {
if(httprequest.readyState == 4 && http.status == 200) {
console.log(httprequest.responseText);
}
}
httprequest.send(parameters);
}
What can I change to pass the adblocker? I mean facebook uses things like ajax in masses to load text and even images in the timeline.
Is there maybe a way to use frames in the background since I don't care about the answer?
After analysing the log as suggested in a comment I found out that log.php seems to be in the blocklist, even if it's on the same server. So name you php files a little more complex to avoid this.
log.php -> submitlog.php

From polling to long polling

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.

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.

Function execute after Ajax request is complete (pure JavaScript)

In my application I use MVC model and Views are built with JavaScript DOM API.
On each page I have to check user's information to find out if session is active and if user's role gives him ability to access that page.
To make this happen, on each page I have "onload" function that triggers "sessionCheck" function which sends AJAX request to controller and returns information with which application makes decisions.
As I said JavaScript is also used to build Views, which means that after "sessionCheck" function I also have "headerView", "sectionView" and other functions that build the structure of page.
So the problem is that, before "sessionCheck" is finished other functions are loaded and nearly for 1-2 seconds users have ability to see what happens on that page and only after that they are transported out of that page by application if that is needed.
I read that there are some solutions in JQuery where "ajax.Complete" functions are available, but I couldn't same solutions in pure JavaScript. Can someone help me to solve this problem ?
This is HTML
<body onload="sessionCheckAdmin(); adminHeaderView(); adminUser(); modalView();">
sessionCheckAdmin functions looks like this
function sessionCheckAdmin()
{
var formData = new FormData();
formData.append("Code", "3");
formData.append("Sequence", "27");
formData.append("TaskId", "All");
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4 && xmlHttp.status == 200)
{
var array = JSON.parse(xmlHttp.responseText);
if(array["userRole"] != "Administrator")
window.location.href = "task.php";
}
}
xmlHttp.open("POST", "../Controller.php");
xmlHttp.send(formData);
}
Part of PHP controller
case 27:
$array = json_encode($_SESSION);
echo $array;
break;

Using JavaScript Ajax to retrieve content from another site

I'm currently experimenting with replacing a number of function I currently use jQuery for with a Vanilla Javascript alternative. This is to:
Increase my understanding of JavaScript as a whole
Make me a better front-end developer (ties into the above)
Improve the speed and responsiveness of my web applications by negating the need for a library such as jQuery for simple tasks.
My aim today is to produce a JavaScript function that allows me to make an Ajax call to another site to retrieve a specific Div and use the content from that Div within my page. I can do this pretty easily with jQuery by filtering the response from an Ajax call with the .find() method to retrieve the specific Div I require then use the .html() function to strip the content and append it to the Div on my site. However, I cannot see an alternative method of doing this using Vanilla JavaScript.
My code so far can be found below:
function fireAjaxRequest(requestType,requestUrl,contentPlaceholder){
var ajaxRequest;
if(window.XMLHttpRequest){
ajaxRequest = new XMLHttpRequest();
}else{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4 && ajaxRequest.status == 200){
contentPlaceholder.innerHTML = ajaxRequest.responseText;
}
}
ajaxRequest.open(requestType,requestUrl, true);
ajaxRequest.send();
}
I call my function as follows:
var contentArea = document.getElementById('news');
fireAjaxRequest('GET', 'http://www.bbc.co.uk',contentArea);
When I load my page, I can see in Firebug that the request completes successfully and I get
a 200 Success response from the Ajax call however, nothing is displayed in my target element. At first I thought this was because you cannot store a whole page within a single element but after altering my code slightly I found the the following snippet of code does not seem to be executed upon the success of the Ajax call:
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4 && ajaxRequest.status == 200){
contentPlaceholder.innerHTML = ajaxRequest.responseText;
}
}
Am I doing something incorrectly here?
You really need to look into XSS. I think you'll understand why there are serious restrictions with what you're trying to do.
If you control both domains, you can use JSONP or CORS.
You could also write send an ajax request to your own server that acts as a proxy. Your server would "forward" the request to the destination server, and relay the response to the client.

Categories

Resources