How can a JavaScript routine call itself? (not recursive!) - javascript

my task is to do a long running JS code. This routine generate a POST request, and when its over and need to, generates another according to the answer:
function routine (a)
{
var answer = createPostRequest (bla bla bla);
if (answer)
{
routine (a);
}
}
so it recursively calls itself as long as the answer is true. So far its good, but then browser freezes, or hangs too much. After a time, Firefox will tell me that script is running too long, and offers to stop it.
Instead of doing routine (a); I tried to do with a setTimeout with timing 1. The same things, but when I set 100 for timing, it looks ok. But there are unnecessarry waitings, plus its a subjective number (what if even that 100 causes problems?)
I need some kind of "message based" thing, like in Delphi/Windows programming: a program sends a message to itself. How can it be achived in JS?
Edit: the way I generating the request:
var ajax = createXmlHttp();
ajax.open ('POST', 'dsdsdsad.adsf', false);
var parameters = 'param=1';
ajax.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
ajax.setRequestHeader ("Content-length", parameters.length);
ajax.setRequestHeader ("Connection", "close");
ajax.send (parameters);
try
{
var answer = eval('(' + ajax.responseText + ')');
}
catch (error)
{
alert ('Error in the answer: '+ajax.responseText);
return;
}

I would assume your createPostRequest makes an AJAX call that can handle a callback.
If so, make sure the request is asynchronous and pass it a callback that tests the condition and makes the next call if needed.
function createPostRequest(address, callback) {
var ajax = createXmlHttp();
ajax.open ('POST', address, true); // make it async
var parameters = 'param=1';
ajax.setRequestHeader ('Content-type', 'application/x-www-form-urlencoded');
ajax.setRequestHeader ("Content-length", parameters.length);
ajax.setRequestHeader ("Connection", "close");
// handle the async response
ajax.onreadystatechange = function() {
if (ajax.readystate == 4) {
try {
callback(eval('(' + ajax.responseText + ')'));
} catch {
callback(null);
}
}
};
ajax.send (parameters);
}
function routine (a) {
createPostRequest (bla bla bla, function(answer) {
if (answer) {
routine (a);
}
}
}

Related

Javascript text file loading delay

I'm loading a .txt file located on my server with this simple method:
function getFileFromServer(url, doneCallback)
{
console.time("getFileFromServer");
var xhr;
xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleStateChange;
xhr.open("GET", url, true);
xhr.send();
function handleStateChange() {
if (xhr.readyState === 4) {
doneCallback(xhr.status == 200 ? xhr.responseText : null);
}
}
console.timeEnd("getFileFromServer");
}
I'm using it in this simple way, accordingly to this post: Reading a txt file from Server, writing it to website
function loadFile( url ) {
console.time("loadFile");
getFileFromServer(url, function(text) {
if (text === null) {
console.log("error-loading-file");
}
else {
console.timeEnd("loadFile");
doStuff(text);
}
});
As you can see I've put the console.time to keep track of the timing. Here's what the browser console answer:
getFileFromServer: 1.744ms
loadFile: 18114.871ms
I'm not a javascript expert, and the only thing I can figure out to explain the timing difference is the argument passing(value vs reference in C++).
Someone can explain me this difference in timing?
The reason why getFileFromServer finishes very fast is that there is no real processing done. The function does not wait until the request returns from the server but only registers the callback function for when it does. That means it took 1.744ms to send the request, nothing more.
The loadFile function is measuring the time between sending the request and actually getting a response. That is the difference.

Javascript - updating textarea freezes browser tab

I am updating text in text area with javascript every 2 seconds, however sometimes happen that entire page freezes and you have to close the tab (other tabs in browser are working normally, this happens to all people visiting the page).
This is how my code looks like:
function ajaxSyncRequest(reqURL) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, false);
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200){
document.getElementById(\"1\").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) { document.getElementById(\"1\").scrollTop = document.getElementById(\"1\").scrollHeight; }
} else {
document.getElementById(\"1\").innerHTML = "Could not connect to remote server!";\n
}
}
}
And this is the 2 seconds timer:
function timer() {
ajaxSyncRequest("ConsoleGenerator");
window.setTimeout("timer()", 2000);
}
I am getting the text with POST method to Java Servlet. It works sometimes for hours and then it freezes and browser says "Page is not reposnding..." or sometimes it works just a few minutes and then it freezes...
Can anybody help please ?
(Assuming we fix the basic syntax errors in the code.) You're happily firing off a subsequent requests without waiting for previous ones to complete. If the ajax call ever takes more than two seconds, you'll have overlapping calls. That isn't a problem in and of itself unless your backend is serializing calls or similar, but it does set up a chaotic situation.
You're also making synchronous requests by specifying false as the third argument to the POST call. There's no need to make the request synchronous, and doing so (particularly every two seconds?!) will indeed tend to lock up the UI of the browser.
I would recommend waiting for the previous request to complete before scheduling the next one, and making the requests asynchronous so the browser UI isn't locked:
// Accept callback --------------v
function ajaxSyncRequest(reqURL, callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", reqURL, true);
// async, not sync ----------^
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlhttp.send('server=" + server + "');
if (xmlhttp.readyState == 4) {
if (xmlhttp.status == 200) {
document.getElementById("1").innerHTML = xmlhttp.responseText;
if (document.getElementById('check').checked) {
document.getElementById("1").scrollTop = document.getElementById("1").scrollHeight;
}
} else {
document.getElementById("1").innerHTML = "Could not connect to remote server!\n";
}
callback(); // <== Call it
}
}
function timer() {
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, 2000);
});
}
That will wait for the ajax to complete and then schedule another update two seconds later. If you want to include the time the ajax call took in the two seconds instead, we can do some basic math:
function timer() {
var started = Date.now();
ajaxSyncRequest("ConsoleGenerator", function() { // Pass in a callback
setTimeout(timer, Max.max(0, 2000 - (Date.now() - started));
});
}
Side note: No need for the window. prefix on setTimeout (though it's harmless provided nothing's shadowed the global window), and rather than passing a string to it, just pass a function reference.

Firefox Extension: multiple requests with XMLHttpRequest. Use Asynchronous or not?

I'm trying something very simple for my first Firefox Add-On, the important part is:
Step 1) Call an external API to retrieve some data.
Step 2) Call that API again with the data retrieved the first time to get some more.
Now, I first implemented it using XMLHttpRequest in synchronous mode, since I thought the need to wait for Step 2 forced me to do it that way. Two calls to the function that dealt with the API call, used XMLHttpRequest and parsed the response. Fine.
Then I came accross various docs in the Mozilla Development Network which encourage you to use XMLHttpRequest in asynchronous mode and so I tried.
Basing my implementation on multiple XMLHttpRequests and others I came up with the code below.
My question is: Is this the proper way to do it? Should I go back to using synchronous mode? It works like this, but it just doesn't strike me as the correct AJAX pattern you would use...
// first call
var username = foo;
var password = bar;
var startOffset = 0; // initial value
var url = encodeURIComponent('https://theapiurl.com/query=' + startOffset);
doRequest();
function doRequest() {
makeRequest(url, username, password);
}
function makeRequest(url, username, password) {
var http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = function() {
alertContents(http_request);
};
http_request.open('GET', url, true, username, password);
http_request.send(null);
}
function alertContents(http_request) {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
if (startOffset == 0) {
startOffset = 45; // this value would be extracted from 'http_request'
url = encodeURIComponent('https://theapiurl.com/query=' + startOffset);
// second call, parameter startOffset has changed
doRequest();
} else {
}
} else {
alert('There was a problem with the request.');
}
http_request.onreadystatechange = function fnNull(){};
}
}
You should always avoid doing synchronous network requests as it will block the GUI from functioning until you get a response. Just because the network may be fast for you, you should not assume it will be fast for all of your users.

Ajax send function wont' fire?

Whenever I run this file the code runs up to the point where the send function fires and then it only fires if I have an alert function directly behind it, if I take out the alert("sent"); out then it replies with ServerReadyyState is:1.
What could possibly be the problem? Someone please help, I've tried it on my local machine and on my personal server and got the same results. Any help is greatly appreciated.
The Code:
/**
* #author d
*/
var xhr;
function getPlants(xhr) {
try {
xhr = new XMLHttpRequest();
} catch (microsoft) {
try {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
xhr = false;
alert("ajax not supported");
}
}
}
xhr.open("GET", "db_interactions.php", true);
xhr.send(null);
alert("sent"); //the send function only works if this alert functions is here
if (xhr.readyState == 4) {
return xhr.responseText;
} else {
alert("Server ReadyState is:" + xhr.readyState);
xhr.abort();
//getPlants(xhr);
}
}
AJAX is asynchronus. You can't just check the ready state immediately after.
The correct design pattern is to assign a function for the AJAX call to run when the ready state changes.
xhr.onreadystatechange = function () { alert('It changed!') }
In that function, you'll want to check if the state is 4. If so, you're ready to process the output. If not, do nothing, since that function will be called a few times before the ready state is 4.
Requests take some amount of time. When adding an alert() the code is being stopped until the user clicks ok. So when you remove it the request is send and immedialty checked. Resulting in an unfinished request.
When you change your code to this:
xhr.onreadystatechange=state_change
xhr.send(null);
function state_change() {
if(xhr.readyState==4) {
return xhr.responseText;
} else {
alert("Server ReadyState is:"+xhr.readyState);
}
}
a certain function like in this case state_change gets called every time the state changes. So you can wait until the request is finished or until an errorcode comes up.

Javascript XMLHttpRequest issue

I am using the following script to monitor whether I can connect to a web site in a regular interval (10 seconds in my sample code). I met with two issues, any ideas how to solve them?
If a web site is very slow and no response within 10 seconds (making PingWebSite not return), I find 2 second call to PingWebSite will be executed because of 10 second interval arrives. My purpose is I want only one call to PingWebSite is under execution, and if 10 seconds interval arrives and previous PingWebSite is executing, I want to prevent current PingWebSite from execution. Any ideas how to solve this?
I find a strange issue, when I connect to a very slow web site, and code path executes to "alert("connecting");", then I expect exception to be thrown for timeout, but in my debug, no exception is thrown. Any ideas how to catch timeout exception?
Here is my code,
var index = 0;
function setup() {
window.setInterval(PingWebSite, (10 * 1000));
}
function PingWebSite() {
var http_request = new XMLHttpRequest();
try {
http_request.open("GET", "http://www.google.com", true);
http_request.onreadystatechange = function() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
MonitorInformation.innerText = "http://www.google.com" + " Connection ok";
alert("ok");
}
else {
alert("fail");
}
http_request = null;
} // if if (http_request.readyState == 4)
else {
// if execute here, no exception will be thrown
alert("connecting");
}
} // end of function
http_request.send(null);
} // try
catch (e) {
alert("service is not available");
}
}
EDIT 1: I have followed advice here to modify my code. Here is the below version. The new issue is index value (e.g. 0) will be prompted in alert message box before ok/fail alert message box. I think index value (e.g. 0) should be prompted in alert message box after ok/fail alert message box. Any ideas why?
var index = 0;
var http_request;
var xhrTimeout;
var chkConn;
function setup() {
chkConn = window.setInterval(PingWebSite, (10 * 1000));
}
function WebMonitorTimeout() {
http_request.abort();
alert("timeout");
index = index + 1;
}
function PingWebSite() {
http_request = new XMLHttpRequest();
http_request.open("GET", "http://www.google.com", true);
http_request.onreadystatechange = function()
{
if (http_request.readyState == 4) {
if (chkConn) { clearInterval(chkConn); }
if (http_request.status == 200) {
alert("ok");
index = index + 1;
if (xhrTimeout) { clearTimeout(xhrTimeout); }
}
else {
alert("fail");
index = index + 1;
if (xhrTimeout) { clearTimeout(xhrTimeout); }
}
http_request = null;
} //if (http_request.readyState == 4)
} // end of event function
http_request.send(null);
xhrTimeout = setTimeout("WebMonitorTimeout();", 30000);
alert(index);
chkConn = window.setInterval(PingWebSite, (30 * 1000));
}
thanks in advance,
George
Duplicate of javascript connect to web site code not working
You can't do Cross Site XHR requests because of browser security
For your first problem, don't use setInterval – use setTimeout in the callback for your request:
http_request.onreadystatechange = function () {
if (http_request.readyState == 4) {
// ...
setTimeout(PingWebSite, 10000);
}
};
Don't forget to call your function once after it has been defined to start it off (after that setTimeout will be called every time after a request has finished.)
Note that in some cases you might not reach readyState 4. I haven't really looked into how other libraries handle those cases, but look at the source code of jQuery, for example, for inspiration.
<SCRIPT language=javascript>
// Needed for IE6 and older to replicate the standard XMLHttpRequest object
if (window.ActiveXObject && !window.XMLHttpRequest){window.XMLHttpRequest =
function(){progIds=new Array("Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.5.0",
"Msxml2.XMLHTTP.4.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP",
"Microsoft.XMLHTTP");for(i in progIds){try{return new
ActiveXObject(progIds[i]);}catch(ex){alert(progIds[i]);}}return null;};}
// Standard asynchonous AJAX code
var xhr = new XMLHttpRequest();
// You would normally trade out the location.href with an actual .ashx
// page. It's like this here only for testing, thereby requesting this
// same page back from the server.
xhr.open("POST",location.href,true);
// The function that will be called asynchronously when the server sends
// back its response
xhr.onreadystatechange=function(){
// If you're using the file system instead of a web server then xhr.status
// will come back as 0, not 200. And of course if the page isn't found
// then a web server will send back a status of 404. xhr.readyState is 4
// when the page is done.
if (xhr.readyState == 4 && xhr.status == 200) {
clearTimeout(xhrTimeout); // Looks like we didn't time out!
// Use xhr.responseText to parse the server's response
alert(xhr.responseText);
}
}
// Now that we're ready to handle the response, we can make the request
xhr.send("My excellent post info");
// Timeout to abort in 5 seconds
var xhrTimeout=setTimeout("ajaxTimeout();",5000);
function ajaxTimeout(){
xhr.abort();
alert("Well dang, the AJAX request timed out. Did you lose network "+
"connectivity for some reason?");
// Note that at this point you could try to send a notification to the
// server that things failed, using the same xhr object.
}
</SCRIPT>

Categories