How to call a callback method after HTTP request - javascript

My code is running inside a main function. One part of my code is to make an HTTP request with an parameter which was defined before in the function and than write the response in to a new variable and work with it later.
I would like to exclude these steps with HTTP Request outside of the main function, and just CALL the function and write the response in a variable.
Unfortunately I tried it, but it doesn't work.
Error: variable is undefined
My code:
function DoWork() {
//some code
var strResponseHttpRequest;
strResponseHttpRequest = HttpRequest(strInput, function(strInput) {
console.log(strInput);
};
//continue working with the variable 'strResponseHttpRequest'
//rest of my code
}
function HttpRequest(strInput, callBackMethod) {
var objRequest = new XMLHttpRequest(); //New request object
objRequest.onreadystatechange = function() {
// Waits for correct readyState && status
if (objRequest.readyState == 4 && objRequest.status == 200) callBackMethod(objRequest.responseText)
}
objRequest.open("get", "php/get-content.php?ID=" + strInput, true);
objRequest.send();
}
I hope you can help me to find out, where the issue is. If there are some better way to do this, let me know. I would be appreciate it. Thank you.

Do you mean an asynchronous callback? You'll want to wait until the server gives back the correct status and readyState.
Change this:
objRequest.onload = function() {
var strResponse = this.responseText;
return strResponse;
};
To this:
objRequest.onreadystatechange = function() {
// Waits for correct readyState && status
if (objRequest.readyState == 4 && objRequest.status == 200) callBackMethod(objRequest.responseText);
};`
and pass in a callback method as a second parameter to HttpRequest(strInput, callbackMethod) like so:
strResponseHttpRequest = HttpRequest(strInput, function(responseText) {
console.log(responseText);
});
Also add callbackMethod as a parameter like so:
HttpRequest(strInput, callbackMethod)

Where is your strInput variable in your DoWork() function coming from? Maybe you forgot to define it somewhere? Could be for example:
function DoWork(strInput) {
//some code
var strResponseHttpRequest;
strResponseHttpRequest = HttpRequest(strInput);
console.log(strResponseHttpRequest);
//continue working with the variable 'strResponseHttpRequest'
//rest of my code
}
function HttpRequest(strInput) {
function reqListener () {
console.log(this.responseText);
}
var objRequest = new XMLHttpRequest(); //New request object
objRequest.onload = function() {
var strResponse = this.responseText;
return strResponse;
};
objRequest.open("get", "php/get-content.php?ID=" + strInput, true);
objRequest.send();
}
DoWork("yourIDvalue");

Related

Return JSON from XMLHttpRequest Function

Hello I've been trying to wrap my head around returning data from a XMLHttpRequest Function. I've tried many different ways but the only thing i can get when i try to output the data to a console from out-side the function i always get 'undefined'. it only works if i do it from inside the function itself.
<script>
var object;
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
var obj1;
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
if (success)
success(JSON.parse(xhr.responseText));
//console.log(data); works here!
} else {
if (error)
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
object = loadJSON('jconfig.json',
function (data) { console.log(data); return($data);/*works here! but does not return!*/ },
function (xhr) { console.error(xhr); }
);
console.log(object);//does not work here
</script>
I know this is a very simple problem but I've been stuck with this problem for over an hour now and the answers given on other similar questions cant seem to get me over this obstacle. Any help is highly appreciated!
EDIT: I updated the code with some suggestions but i still cant get ti to work. Any suggestions to get the code above to finally return something i can use outside of the functions.
The line console.log(object) is executed just after the laodJSON() function is called and the JSON object isn't loaded till then.
This is related to callbacks and async functions. Your loadJSON() can only actually load the JSON when it get's response from the server.
Instead, if you want to call the JSON object outside the loadJSON() function, you need to use a callback function. Something like this:
<script>
var object;
function loadJSON(path, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// Here the callback gets implemented
object = JSON.parse(xhr.responseText);
callback();
} else {
}
}
};
xhr.open("GET", path, true);
xhr.send();
return xhr.onreadystatechange();
}
loadJSON('jconfig.json', function printJSONObject(){
console.log(object);
});
// this will not work unless you get the response
console.log(object);
</script>
Update: "Returning" a value from an async function by the use of callbacks is pointless, since the next line of code will be executed immediately without waiting for the response.
Instead, if you want to use the object outside of the function sending an XHR request, implement everything inside your callback function.

AJAX, pass additional variable to callback and store XMLHTTLRequest.response to variable

I am trying to read a local file on the server with a standard function loadDoc(url, cfunc), then
1) search for a particular string in the file (getLine());
2) if possible, store that line to a variable.
For point 1 I pass a string to the callback.
2) Getting the response is problematic because XMLHTTPRequest is asynchronous. At this moment the error is:
"ReferenceError: xhttp is not defined"
function main(){
var url="data.txt"
var str="1,0,"; //just an example
var myCallBackWithVar = function(){
getLine(str);
};
loadDoc(url, myCallBackWithVar);
//Can I get the line here somehow?
}
function loadDoc(url, cfunc) {
var xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
cfunc(xhttp);
}
}
xhttp.overrideMimeType('text/plain');
xhttp.open("GET", url, true);
xhttp.send();
}
//Find string with the desired data in txt file
function getLine(str) {
var data=xhttp.responseText;
//Find the line from the txt file
var start=data.indexOf(str);
var end=data.indexOf(";",start);
var line=data.substring(start,end);
return line;
}
data.txt is something like this:
some data here
0,0,9;
1,0,10;
1,1,11;
I have already tried to pass the XMLHTTPRequest objetct getLine(xhttp,str). How to solve points 1 and 2? I'd rather keep it jQuery free for the moment. Thanks
Can I get the line here somehow?
I don't think that's a good idea. You can't be sure that your app will work correctly. XHR is a async function and you should use async architecture.
Here the example how this functionality can be done.
var text; // define global variable
var str = "1,0,"; //just an example
function main(){
var url = "data.txt";
var cb = function (data){
text = getLine(data);
// you can use text var here
// or in anyewhere in your code
}
loadDoc(url, cb);
}
function loadDoc(url, cb) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
cb(xhr.responseText);
}
}
xhr.overrideMimeType('text/plain');
xhr.open("GET", url, true);
xhr.send();
}
//Find string with the desired data in txt file
function getLine(data) {
if(data) {
//Find the line from the txt file
var start = data.indexOf(str);
var end = data.indexOf(";", start);
var line = data.substring(start, end);
return line;
}
}
On complete, you don't need to pass the whole xhttp variable through too the callback function. When you do this:
function getLine(str) {
var data=xhttp.responseText;
xhttp is already out of scope. To fix this, the parameter name would also have to be xhttp.
A better way would be to do :
cfunc(xhttp.responseText);
and then
var data=str
This way, you are passing only what you need as an argument.

Returning ajax data to different functions corresponding to different links

I'm at peak-frustration trying to resolve my mental block re: callbacks. I've read How to return value from an asynchronous callback function? and How to return the response from an Ajax call? (among many other posts), and indeed the latter was helpful with another problem. However what I'm trying to do now is just slightly different and I'm losing my mind trying to adapt it to my code. Maybe my approach is entirely wrong/fundamentally flawed (and not just immature, which I can live with)?
The essence of my problem is that rather than simply returning ajax result to a callback function, I need the resulting json to be available to different functions, corresponding to different events, i.e.:
linkOne.onclick = invoke ajaxReq + getJsonData, then call functionOne with getJsonData result as an argument
linkTwo.onclick = invoke ajaxReq + getJsonData, then call functionTwo with getJsonData result as an argument
linkThree.onclick = invoke ajaxReq + getJsonData, then call functionThree with getJsonData result as an argument
Can't this be done with the link.onclick definition? Why doesn't this work:
linkThree.onclick = functionOne(getJsonData);
Here's my code:
function ajaxReq() {
var request = new XMLHttpRequest();
return request;
}
function getJsonData() {
var request = ajaxReq();
request.open("GET", "/myJSON.json", true);
request.setRequestHeader("content-type", "application/json");
request.send(null);
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
var myJsonString = JSON.parse(request.responseText);
var myJsonArray = myJsonString["An Array in myJSON.json"];
// functionOne(myJsonArray); // callback: what if I need to pass this value to various functions?
return myJsonArray; // ... 'cause this ain't doin' it, and I don't know why
}
}
} // onreadystatechange
} // getJsonData
function functionOne(myJsonArray) {
var myJsonArray = getJsonData(); // why doesn't this work, since, in getJsonData, var request = ajaxReq(); returns an ajax request ?
}
And why, if var request = ajaxReq(); invokes ajaxReq function and returns its result to getJsonData, does var myJsonArray = getJsonData(); in functionOne not do the same?
Any help with this is much appreciated. (p.s. seeking a pure javascript fix, not jQuery.)
svs
As it has been answered in the links you have specified, that we cannot return value from asynchronous call to use it in a synchronous function call. So here is the trick -
Assign all the onclick listeners a common function.
link1.onclick = someCommonfunction;
link2.onclick = someCommonfunction;
link3.onclick = someCommonfunction;
And define the common function like following, which will have json data in the callback, and you can pass that data to any function call.
function someCommonfunction(e) {
/* this is the function which will be finally executed with json data after clicking */
var callback = function(jsonData) {
var myJsonArray = jsonData;
//do some condition check and call functionOne, functionTwo or functionThree
};
getJsonData(callback);
}
I modified getJsonData to call callback with the response data.
function getJsonData(callback) {
var request = ajaxReq();
request.open("GET", "/myJSON.json", true);
request.setRequestHeader("content-type", "application/json");
request.send(null);
request.onreadystatechange = function() {
if (request.readyState === 4) {
if (request.status === 200) {
var myJsonString = JSON.parse(request.responseText);
var myJsonArray = myJsonString["An Array in myJSON.json"];
callback(myJsonArray);
}
}
} // onreadystatechange
} // getJsonData

Vanilla Javascript Ajax call inside IIFE not responding

Hey guys I'm running an IIFE and an ajax call and it seems to not respond at all...
var $ = {
core:function(u){
return new $.httpRequest(u);
},
httpRequest:function(url){
var text;
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (this.readyState != 4 || this.status != 200) return;
text = this.responseText;
};
r.send();
console.log(text);
return text;
}
};
Is there something silly I am missing? Just been over this a few times and I have my hands full and hope that our savvy SO members could help out. Should I place the return inside the onload?
The onreadystatechange function you assign is where you need to handle the responseText. You need to either process it there or call some function and pass it the data. Remember, the ajax call is asynchronous which means that you start it with your r.send(), your $.httpRequest() function finishes, your other javascript after it executes and then some time later the ajax call completes and calls your onreadystatechange function. At that point, all you can do is to either process the data right there in that function or call some other function and pass the data to it.
Here's one way of doing it using a callback function that you pass into your httpRequest function:
var $ = {
core:function(u){
return new $.httpRequest(u);
},
httpRequest:function(url, callback){
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
callback(r.responseText);
};
r.send();
}
};
Example usage:
$.httpRequest("http://examplesite.com/myurl", function(data) {
// write code here to process the data
});

Unable to return an object's value from a JavaScript function

I have a function which attempts to capture a return value from a calling function in the following manner:
var select = xhrRetrieve(projID);
Here is an example of the xhrRetrieve function:
function xhrRetrieve(projID) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
return obj.select.toString();
}
}
}
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
}
I am using jQuery in conjunction with straight JavaScript. Whenever I attempt to get the value of obj.select using:
var select = xhrRetrieve(projID);
Select always comes back undefined.
What am I doing wrong?
The function doesn't return anything
The moment you call your function, the (not currently present) return value is being assigned to select. At the same moment, your ajax request is being fired, which takes time to complete; the callback function will not be called until the ajax request has completed (and succeeded).
This should work:
function doStuffWithTheAjaxResponse(select) {
// do stuff
}
function xhrRetrieve(projID) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
doStuffWithTheAjaxResponse(obj.select.toString());
}
}
}
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
xhr.open("POST",url);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
}
Since the request is asynchronous the function will return before your code in onreadestatechange fires. You can switch to synchronous and get the value before the function returns:
function xhrRetrieve(projID) {
var returnVal;
var xhr = new XMLHttpRequest();
var url = "ajax.cgi";
var data = "action=retrieve-opp&proj-id=" + projID;
//3rd param is false to switch to synchronous
xhr.open("POST",url, false);
xhr.setRequestHeader("Content-Type","application/x-www-urlencoded");
xhr.send(data);
if(xhr.readyState == 4) {
if(xhr.status == 200) {
var obj = $.parseJSON(xhr.responseText);
return obj.select.toString();
}
}
}
The function xhrRetrieve doesn't have a return value. What do you expect to happen?
You have two functions there. The inner function returns a value, but not the outer one. The inner function is an event handler so the return value doesn't go anywhere. Your XMLHttpRequest is asynchronous, so you won't get a return value right away. See this post for a more detailed explanation: parameter "true" in xmlHttpRequest .open() method

Categories

Resources