Why does this JavaScript code ignore the timeout? - javascript

Question:
Consider the below JavaScript code, which works fine so far, except...
... that it completely ignores the timeout.
Why ?
I tested it with sleeping 10s in the ashx handler (timeout is set to 5s), and so far it never complained about timeout. I will increase the timeout for production use, of course.
function createXMLHttpRequest()
{
try { return new XMLHttpRequest(); } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
alert("XMLHttpRequest not supported");
return null;
}
function ExecuteSQL(strParameter1, strParameter2, strParameter3)
{
try
{
strParameter1 = encodeURIComponent(strParameter1);
strParameter2 = encodeURIComponent(strParameter2);
strParameter3 = encodeURIComponent(strParameter3);
var xhReq = createXMLHttpRequest();
var dtNow = new Date();
var dt = Date.parse(dtNow) + dtNow.getMilliseconds()
var params = "prm1=" + strParameter1 + "&prm2=" + strParameter2 + "&prm3=" + strParameter3 + "&prm4=END";
params = params + "&NoCache=" + dt;
//var URLget = "cgi-bin/RequestData.ashx?NoCache=" + dt + "&param1=value1&param2=value2";
var URLpost = "cgi-bin/RequestData.ashx?NoCache=" + dt;
xhReq.open("POST", URLpost, false);
//Send the proper header information along with the request
xhReq.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhReq.setRequestHeader("Content-length", params.length);
xhReq.setRequestHeader("Connection", "close");
/*
xhReq.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT");
*/
var MAXIMUM_WAITING_TIME = 5000;
var requestTimer = setTimeout(function () {
xhReq.abort();
alert("Request cancelled. \nReason: Timeout (" + MAXIMUM_WAITING_TIME/1000 + "s) exceeded.");
// Handle timeout situation, e.g. Retry or inform user.
}, MAXIMUM_WAITING_TIME);
xhReq.send(params);
if (xhReq.status != 200) {
clearTimeout(requestTimer);
if (xhReq.status == 400)
{
var serverResponse = xhReq.responseText;
alert(unescape(serverResponse));
}
else
alert("XMLHttpRequest Error\nHTTP Status: " + xhReq.status + "\nStatusText: " + xhReq.statusText);
}
else {
clearTimeout(requestTimer);
// Handle error, e.g. Dis
var serverResponse = xhReq.responseText;
alert("Successfully return from execution.");
//alert(unescape(serverResponse));
}
} catch (ex) {
alert("Error in JavaScript-function \"ExecuteSQL\".\nError description: " + ex.Description);
}
} // End Sub ExecuteSQL

I'm going to delete everything that has nothing to do with the timer and see if your problem becomes incredibly obvious.
function something()
{
var requestTimer = setTimeout(function () {
alert("something");
}, 1);
if (something) {
clearTimeout(requestTimer);
}
else {
clearTimeout(requestTimer);
}
}

define this variable var requestTimer outside function ExecuteSQL

You are making a synchronous call using XMLHTTPRequest. Try making it async by changing false to true in the following call:
xhReq.open("POST", URLpost, true);
Currently, due to your sync call the timeout gets cancelled.

Related

Image from JavaScript to PHP as Post Variable

I've seen lots of variations on this question, but none of them applies to this specific situation. I'm a bit confused because of all the data and object types.
Consider the following code in JavaScript:
function postRequest(url, params, success, error, keepactive = 1)
{
let req = false;
try
{
// most browsers
req = new XMLHttpRequest();
} catch (e)
{
// IE
try
{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e)
{
// try an older version
try
{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e)
{
return false;
}
}
}
if (keepactive === 0)
{
ajaxcalls.push(req);
console.log(ajaxcalls.length + ' calls active');
} else if (keepactive === 2)
{
console.log('Filter call: ' + ajaxcalls.length + ' calls active');
filtercall = req;
} else if (keepactive === 3)
{
console.log('Jump call: ' + ajaxcalls.length + ' calls active');
jumpcall = req;
}
if (!req) return false;
if (typeof success != 'function') success = function ()
{
};
if (typeof error != 'function') error = function ()
{
};
req.onreadystatechange = function ()
{
if (req.readyState === 4)
{
// Success! Remove req from active calls.
if (keepactive === 0)
{
for (let i = ajaxcalls.length - 1; i >= 0; i--)
{
if (ajaxcalls[i] === req)
{
ajaxcalls.splice(i, 1);
console.log(ajaxcalls.length + ' calls active');
}
}
}
return req.status === 200 ?
success(req.responseText) : error(req.status);
// dus eigenlijk displayUpdateWorksheet(req.responseText)
// dus eigenlijk displayUpdateWorksheetError(req.status)
}
}
req.open("POST", url, true);
req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
req.send(params);
return req;
}
function uploadPicture(myindex, stringid)
{
let file = document.getElementById("file").files[0];
let contents = new FileReader(); // no arguments
contents.readAsDataURL(file);
contents.onload = function ()
{
// console.log(contents.result);
let filename;
let client;
let field = myindex;
let filecontainer = document.getElementById('file' + myindex);
if (filecontainer != null)
{
filename = filecontainer.innerHTML.replace(/\+/g, '+').replace(/&/g, '&').replace(/#/g, '#').replace(/%/g, '%');
}
let clientcontainer = document.getElementById('myclient');
if (clientcontainer != null)
{
client = clientcontainer.innerHTML.replace(/\+/g, '+').replace(/&/g, '&').replace(/#/g, '#').replace(/%/g, '%');
}
alert('Picture uploaded!');
// let post_array = { client: client, stringid: stringid, filename: filename, field: field, contents: contents.result }
postRequest(
'ajaxcalls/ajaxUploadPicture.php', // url
'&client=' + client +
'&stringid=' + stringid +
'&filename=' + filename +
'&field=' + myindex +
'&contents=' + contents.result +
'&type=' + file.type,
function (responseText)
{
return drawOutputUploadPicture(myindex, responseText);
}, // success
drawErrorUploadPicture // error
);
}
contents.onerror = function ()
{
console.log(contents.error);
};
};
And the following PHP:
$data = $_POST['contents'];
$contents = preg_replace('#data:image/[^;]+;base64,#', '', $data);
$contents = base64_decode($contents);
...
file_put_contents($file_full, $contents);
($file_full is correct here: the file is saved at the right spot. I've just cut some irrelevant code there: nothing in $contents is changed after this.)
When I upload a 52K image, I lose about 1K and the resulting image cannot be opened. What's going on?
The main issue is that 1) I'm using POST with 2) multiple variables and 3) Vanilla JavaScript. I've seen no working examples of that.
When I open the original and copy as text, the beginning is the same:
Original: ���� JFIF ` ` ���Exif
Copy: ���� JFIF ` ` ���Exif
Then a series of NUL's in both files. Then the files start deviating:
Original:
2021:07:22 16:21:52 2021:07:22 16:21:52 L o e k v a n K o o t e n ��"http://ns.adobe.com/xap/1.0/ <?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x="adobe:ns:meta/"><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:dc="http://purl.org/dc/elements/1.1/"/><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreateDate>2021-07-22T16:21:52.056</xmp:CreateDate></rdf:Description><rdf:Description rdf:about="uuid:faf5bdd5-ba3d-11da-ad31-d33d75182f1b" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:creator><rdf:Seq xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:li>Loek van Kooten</rdf:li></rdf:Seq>
</dc:creator></rdf:Description></rdf:RDF></x:xmpmeta>
Copy:
2021:07:22 16:21:52 2021:07:22 16:21:52 L o e k v a n K o o t
e n
�BȚ��ۜ˘YؙK���K�\�K���X��]�Y�[�I�����YI��SL\�ZR��Tޓ�ޚ��Y �σB��\Y]H[�ΞH�YؙN��ΛY]Kȏ������[�Μ��H������˝�˛ܙ��NNNK��̌�\��\�[�^[��ȃ�&Fc�FW67&�F���&Fc�&�WC�'WV�C�fcV&FCR�&6B�F�C3�C36CsS�&c""����3�F3�&�GG���W&���&r�F2�V�V�V�G2���"���&Fc�FW67&�F���&Fc�&�WC�'WV�C�fcV&FCR�&6B�F�C3�C36CsS�&c""����3����&�GG����2�F�&R�6�������
���� ɕ�ѕ�є����Ĵ�ܴ��P�������ȸ�������
ɕ�ѕ�є��ɑ���͍ɥ�ѥ����ɑ���͍ɥ�ѥ���ɑ�酉�����ե�际�Չ��Ե��͐��ő�����ĵ��͐����ɘň��ᵱ��鑌����輽��ɰ��ɜ�����������̼ĸļ�<dc:creator����\H[�Μ��H������˝�˛ܙ��NNNK��̌�\��\�[�^[��ȏ����O��Z��[����[�ܙ��O�ܙ���\O�B�BBO�ΘܙX]܏�ܙ��\�ܚ[ۏ�ܙ�����������WF4
Anyone recognizes what's going on here?
For some reason, in this case $_POST['contents'] contains spaces. If I replace these with + the image comes out nicely. I imagine that when a file is sent as a $_POST variable, it gets split with a space every so many characters.

How can i display as ajax-response in a reloaded page

I have the following situation in an AJAX-Request:
function getFileContens(OBJ) {
var file = OBJ.id;
PARAMS = "Action=getFileContens";
PARAMS = PARAMS + "&File=" + OBJ.id;
var probenZahl = file.split("__")[4];
document.getElementById("inpProbenAnzahl").value = probenZahl;
//setSessionValue(document.getElementById("inpProbenAnzahl"));
try {
if (window.XMLHttpRequest) {
req = new XMLHttpRequest();
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Ihr Webbrowser unterstuetzt leider kein Ajax!");
}
//alert(PARAMS);
req.open("POST", "./php/ajax/Eingabe.php", true);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.onreadystatechange = function() {
cbGetFileContens();
};
req.send(PARAMS);
} catch (e) {
alert("Fehler: " + e);
}
}
function cbGetFileContens() {
if (4 == req.readyState) {
if (200 != req.status) {
alert("Fehler " + req.status + ": " + req.statusText);
} else {
//alert(req.responseText);
var ar_resp = req.responseText.split(";;;");
for (let i = 0; i < ar_resp.length; i++) {
ar_inp = ar_resp[i].split("##");
if (ar_inp[0].trim().length > 2) {
if (document.getElementById(ar_inp[0].trim())) {
document.getElementById(ar_inp[0].trim()).value = ar_inp[1];
}
}
}
location.reload();
//console.log("Hallo");
console.log(req.responseText);
}
}
}
This code shoud display the splitted response-text in a textfield with certain IDs in a HTML-File...
I want to use the Ajax-response-text after reloading the page..
Everything works fine whe i do not reload the page..
Using reloading the text is not displayed..
You can store the response into a session storage.
sessionStorage.setItem('ajax_response', req.responseText)
location.reload();
After, when the page is loaded, you can put the item into your element.
var el = document.getElementById('elemId')
el.innerText = sessionStorage.getItem('ajax_response')

Ajax Post from client side to server side to log errors

I'm trying to create an ajax post function which can log the errors at run time and send them silently to the server side for
This is the Code that i gave to post the data from the client side page
var isDebugging = false;
var logJsErrors = true;
alert('passed variable decleration');
function ErrorSetting(msg, file_loc, line_no) {
alert('entered the error setting method');
var e_msg = msg;
var e_file = file_loc;
var e_line = line_no;
var error_d = "Error in file: " + file_loc +
"\nline number:" + line_no +
"\nMessage:" + msg;
if (logJsErrors) {
theData = "file=" + file_loc + "&line=" + line_no + "&err=" + msg;
alert('passed logging errors');
ajaxCtrl(
function () {
return true;
}, "http://localhost:57410/ServerPage.aspx", theData
);
alert('passed the ajax post');
}
if (isDebugging)
alert("Error Found !!!\n--------------\n" + error_d);
return true;
}
window.onload = ErrorSetting;
This is the definition for Ajax post function
var callInProgress = false;
var xmlHttp;
function ajaxCtrl(fnfragment,theUrl,theData){
var bAsync = true;
this.xmlHttp = XmlHttp.create();
if(theUrl)
var url = theUrl;
else{
alert('Target URL is Empty');
return false;
}
try {
xmlHttp.open("POST", url,bAsync);
callInProgress = true;
}catch(e){
callInProgress = false;
return false;
}
if (bAsync) {
xmlHttp.onreadystatechange= function(){
//alert(xmlHttp.readyState);
switch (xmlHttp.readyState) {
case 4:
callInProgress = false;
if(fnfragment){
fnfragment();
// Clean up so IE doesn't leak memory
//delete xmlHttp.onreadystatechange;
//xmlHttp = null;
}
break;
}
/* if(xmlHttp.readyState == 4){
callInProgress = false;
if(fnfragment){
fnfragment();
// Clean up so IE doesn't leak memory
//delete xmlHttp.onreadystatechange;
//xmlHttp = null;
}
} */
}
}
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=UTF-8");
if(theData)
theKeyValPair = theData;
else
theKeyValPair = "";
try {
callInProgress = true;
xmlHttp.send(theKeyValPair);
}
catch (e) {
callInProgress = false;
alert("Could not contact Server at this Time. Please Try again Later");
return false;
}
if (!bAsync) {
done();
}
}
This is the VB Script that i have tried to add to the server side to get the data from the client page
IF (request.form("") && request.form("file")!="") THEN
Set fcontent = Date+request.form("file")+"\t"+request.form("line")+"\t"+request.form("err")+"\r\n"
MsgBox(fcontent);
WriteToFilecustom(fcontent)
END IF
function WriteToFilecustom(log)
set filename = "Logs\errorlog.txt"
Dim fso, fs,tfile,fo
Set fso = CreateObject("Scripting.FileSystemObject")
IF (fso.FileExists(filename)) then
const ForAppending =8
Set tfile = fso.OpenTextFile(filename, ForAppending ,true)
tfile.WriteLine(log)
else
Set fo=fso.GetFolder(".\Logs")
Set tfile=fo.CreateTextFile(name,false)
tfile.WriteLine(log)
END IF
tfile.Close
Set fo = Nothing
Set fso = Nothing
end function
I don't understand where i am going wrong as my post method is calling the URL but i'm unable to post the data

Update DOM object in time intervals using JavaScript Worker

I'm trying to do some DOM objects updates in background.
What I mean is update tab title, and some elements regardless if user has tab active or not ( to show that there are new notifications )
I already found out, that Worker has to be used as it runs in background ( but don't have access to DOM). Tried as follows:
Main HTML:
...some html
<script>
$(document).ready(function ($) {
if (window.Worker) {
console.log('[DEBUG] Worker is supported')
var eventsWorker = new Worker("<c:url value="/resources/js/eventTimer.js" />");
setInterval(eventsWorker.postMessage([appUrl]), 20 * 1000);
//setEventsNonWorker()
eventsWorker.onmessage = function (e) {
console.log('Message received from worker' + e.data);
setEventsCount(e.data, appName, eventsTxt);
}
} else {
console.log('[DEBUG] Worker is NOT supported')
setEventsNonWorker()
}
});
function setEventsNonWorker(){
//regular update with setTimout and stuff
}
worker javascript file
function setEventsCount(count, appName, eventsTxt) {
var bell, text, countPar;
if (count > 0) {
bell = '<i class="fa fa-bell"></i> ';
countPar = '(' + count + ') ';
text = bell + eventsTxt + countPar;
$(".event-menu-li").html(text);
$("#event-menu-icon").html(bell + count)
document.title = countPar + appName;
} else {
bell = '<i class="fa fa-bell-o"></i> ';
text = bell + eventsTxt;
$(".event-menu-li").html(text);
$("#event-menu-icon").html(bell)
document.title = appName;
}
}
onmessage = function (e) {
var appUrl = e.data[0];
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === XMLHttpRequest.DONE && xmlhttp.status === 200) {
postMessage(xmlhttp.responseText);
}
};
xmlhttp.open("GET", appUrl, true);
xmlhttp.send();
}
The first call is working ( the event count is properly set ) but there are no more calls in 20 sec
Ok it turns out I was putting timeout in wrong place
html should be
//...
eventsWorker.postMessage([appUrl]);
eventsWorker.onmessage = function (e) {
console.log('Message received from worker' + e.data);
setEventsCount(e.data, appName, eventsTxt);
//...
which will just init worker , while worker.js should have the timeout
//...
onmessage = function (e) {
var appUrl = e.data[0];
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === XMLHttpRequest.DONE && xmlhttp.status === 200) {
postMessage(xmlhttp.responseText);
}
};
xmlhttp.open("GET", appUrl, true);
xmlhttp.send();
setInterval(function () {
xmlhttp.open("GET", appUrl, true);
xmlhttp.send();
}, 20*1000);
}

XMLHttpRequest sends local data twice

I'm using XMLHttpRequest's send method to upload the data that are saved in a local sqlite database, to my own website. On my website I'm running phpMyAdmin. The issue that I'm having is that the data gets transmitted to the server twice, even though the local sqlite database stores the data only once. I was wondering if anyone could help me to identify the issue. I also made sure to use XMLHttpRequest asynchronously, I still don't understand why is this happening. Any help would be greatly appreciated. Thank you.
postData: function(count) {
var surveyURL = "https://example.com/data/logging/answer.php";
var file = FileUtils.getFile("ProfD", ["ext.sqlite"]);
var dbConn = Services.storage.openDatabase(file);
var query = dbConn.createStatement("SELECT * FROM responses");
var i = 0;
while (query.step()) {
let data = {
'rowid' : query.row.rowid,
'timestamp' : query.row.timestamp,
'uid' : query.row.uid,
'warning' : query.row.warning,
'ignored' : query.row.ignored,
'domain' : query.row.domain,
'qid' : query.row.qid,
'response' : query.row.response
};
let xmlhttp = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
xmlhttp.open("POST", surveyURL, true);
xmlhttp.timeout = 5000;
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
if (/^0: Survey \d+ added/.test(xmlhttp.responseText)) {
//data was added successfully, delete the row id from local database
let matches = xmlhttp.responseText.match(/^0: Survey \d+ added \((\d+)\)/);
let rowid = matches[1];
ext.Debug.dump("Deleting row " + rowid);
try {
//commented this line out, because at first I thought this was the issue but itsn't?!
//dbConn.executeSimpleSQL("DELETE FROM responses WHERE rowid=" + rowid);
} catch(e) {
ext.Debug.dump("Error deleting row: " + e);
}
} else {
ext.Debug.dump("Remote error: " + xmlhttp.responseText);
}
}
}
try {
xmlhttp.send(ext.js.toString(data));
} catch (e) {
ext.Debug.dump("Error transmitting results: " + e);
}
query.reset();
},
testConnection: function() {
//checks whether we can reach our server
//only test the connection if we have stuff to upload
//do this asynchronously
var file = FileUtils.getFile("ProfD", ["ext.sqlite"]);
var dbConn = Services.storage.openDatabase(file);
var query=dbConn.createStatement("SELECT count(*) FROM responses");
query.executeAsync({
handleResult: function(aResultSet) {
let count = aResultSet.getNextRow().getResultByIndex(0);
ext.Debug.dump(count + " records to upload");
if (count>0) {
var testURL = "https://example.com/data/connected.php";
var xmlhttp = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance();
xmlhttp.open("POST", testURL, true);
xmlhttp.timeout = 5000;
var date = Date.now();
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
if (xmlhttp.responseText == date) {
ext.js.postData(count);
ext.Debug.dump("connected!");
} else {
ext.Debug.dump("not connected");
}
} else {
ext.Debug.dump("not connected");
}
}
xmlhttp.ontimeout=function() {
ext.Debug.dump("not connected! 3");
}
try {
xmlhttp.send("time=" + date);
} catch (e) {
ext.Debug.dump("Error connecting: " + e);
}
}
},
handleError: function(aError) {
ext.Debug.dump("Error: " + aError.message);
},
});
dbConn.asyncClose();
},

Categories

Resources