Return datas inside XMLHttpRequest.onreadystatechange [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have this function :
function getDatas() {
var xmlhttp = new XMLHttpRequest();
var response = null;
xmlhttp.open("POST", "getdatas.php", true);
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState === 4) {
if(xmlhttp.status === 200) {
response = xmlhttp.responseText;
return response;
}
else {return xmlhttp.statusText;}
}
};
xmlhttp.send(null);
}
The response is in a JSON format and correctly filled.
How to return the response for another use like :
var datas = getDatas();
UPDATE :
After the callback I have this :
function AppViewModel() {
var _self = this;
getDatas(function(error, result) {
if(error) {
alert(error);
} else {
_self.datas = result;
console.log(_self.datas);
}
});
console.log(_self.datas);
}
The first console.log(_self.datas); works well but the second is undefined.

AJAX is asynchronous, so you don't return any values from such functions, you use callbacks and use the value inside the callback:
function getDatas(callback) {
var xmlhttp = new XMLHttpRequest();
var response = null;
xmlhttp.open("POST", "getdatas.php", true);
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState === 4) {
if(xmlhttp.status === 200) {
response = xmlhttp.responseText;
callback(null, response);
}
else {
callback(xmlhttp.statusText, null);
}
}
};
xmlhttp.send(null);
}
and then when you call the getDatas function you provide a callback which will be invoked when the AJAX request finishes and it will either contain the result or an error:
getDatas(function(error, result) {
if (error) {
alert('An error occurred while retrieving data: ' + error);
} else {
// Use the result variable here
}
});

Related

undefined response getting in javascript function ejs

I am trying to get status of any address,in which request_withd function is call ,then action goes on another function named 'is_address_exist' which is return response status of any address in
'yes' or 'no' but i am getting 'undefined' response message in console.
function is_address_exist(address) {
var xmlhttp = new XMLHttpRequest();
var url = '../ withdrawn/address_check/' + address;
xmlhttp.open('GET', url, true);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
if (xmlhttp.status === 200) {
return xmlhttp.responseText;
}
}
}
}
function request_withd(e) {
var response_status = is_address_exist(address);
console.log(response_status);
}
The onreadystatechange function is a call back function, it runs async, it should have the intended actions included in its definition. This should work.
function is_address_exist(address){
var xmlhttp=new XMLHttpRequest();
var url='../withdrawn/address_check/'+address;
xmlhttp.open('GET',url,true);
xmlhttp.send();
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState===4)
{
if(xmlhttp.status===200){
console.log(xmlhttp.responseText);
}
}
}
}
function request_withd(e){
is_address_exist(address);
}
Or for non async function
function is_address_exist(address) {
var responseText ="";
var xmlhttp = new XMLHttpRequest();
var url = '../ withdrawn/address_check/' + address;
xmlhttp.open('GET', url, false);
xmlhttp.send();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
if (xmlhttp.status === 200) {
responseText = xmlhttp.responseText;
}
}
}
return responseText;
}
function request_withd(e) {
var response_status = is_address_exist(address);
console.log(response_status);
}
is_address_exist() doesn't return anything here.
Your return is happening within a xmlhttp.onreadystatechange = () => ...
You could either use callbacks or promises here.
Callback example:
function is_address_exist(address, handler){
//...
xmlhttp.onreadystatechange = function(){
//...
handler(xmlhttp.responseText);
});
}
is_address_exist('...', function(data){
console.log(data);
});
Promise example:
function is_address_exist(){
return new Promise(function (resolve, reject) {
//...
xmlhttp.onreadystatechange = function(){
//...
resolve(xmlhttp.responseText);
});
xmlhttp.onerror = reject;
});
}
is_address_exist()
.then(function (data) {
console.log(data)
})
.catch(console.error.bind(console));

return value from onreadystatechange with callback [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I'm trying to return a value from an onreadystatechange AJAX call... I found this page : stackoverflow link. I though I had it working but realised that it made no difference to add or remove the fn function. The following code works :
username_is_available();
function username_is_available() {
var username = document.getElementById('username').value;
get_data('username', username, function(returned_value) {
if (returned_value == 'true') {
document.getElementById('username_err').innerHTML = 'Taken';
} else {
document.getElementById('username_err').innerHTML = 'Available';
};
});
}
function get_data(data_type, data, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText);
}
};
xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
xmlhttp.send();
}
It all works fine but that's not my goal, I would like a function username_is_available() that returns true if the username is indeed available.
Instead, here I an action happens (innerHTML is changed). And if I try and do a return in the anonymous function I get the same result as if I had returned it from directly inside the onreadystatechange : var unasigned
Unfortunately, since the process to determine if a username is taken is asynchronous, there is no way to simply return a value of true or false from the function call. What you can do is set up something similar to what you have now (callbacks) using language features specifically designed for this exact purpose.
A Promise is one of these features.
Usage would look something roughly like this:
function username_is_available(username) {
return new Promise(resolve => {
get_data("username", username, resolve);
});
}
function get_data(data_type, data, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText == "true");
}
};
xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
xmlhttp.send();
}
// Usage:
username_is_available("Ivan").then(available => {
let text = available ? "Available" : "Taken";
document.getElementById("username_err").innerHTML = text;
});
This relies on availablity.php returning true and false as text, which is converted to a Boolean before resolve is called.
In the future, when ES7+ async and await directives are available, using the promise will be as simple as this (note the await keyword):
let available = await username_is_available("Ivan");
let text = available ? "Available" : "Taken";
document.getElementById("username_err").innerHTML = text;
Edit: If you can't use ES6 or promises, it's back to good ol' callbacks!
function username_is_available(username, callback) {
get_data("username", username, callback);
}
function get_data(data_type, data, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText == "true");
}
};
xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
xmlhttp.send();
}
// Usage:
username_is_available("Ivan", function(available) {
var text = available ? "Available" : "Taken";
document.getElementById("username_err").innerHTML = text;
});
I've been playing around with observers as an alternative to promises. I set up a an example in plnkr to show how it can work. I think in your case it would look like this:
function Producer() {
this.listeners = [];
}
Producer.prototype.add = function(listener) {
this.listeners.push(listener);
};
Producer.prototype.remove = function(listener) {
var index = this.listeners.indexOf(listener);
this.listeners.splice(index, 1);
};
Producer.prototype.notify = function(message) {
this.listeners.forEach(function(listener) {
listener.update(message);
});
};
var notifier = new Producer;
function get_data(data_type, data) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
notifier.notify(xmlhttp.responseText);
}
};
xmlhttp.open("GET", "availability.php?" + data_type + "=" + data, true);
xmlhttp.send();
}
var username_is_available = {
update: function(returned_value) {
var username = document.getElementById('username').value;
if (returned_value == 'true') {
document.getElementById('username_err').innerHTML = 'Taken';
} else {
document.getElementById('username_err').innerHTML = 'Available';
};
}
}
notifier.add(username_is_available);
get_data("username", username);
Note the Producer code is reusable, you would make a new instance for other ajax/observable requests.

How to catch XMLHttpRequest onreadystatechange function result?

I want to catch the returned value of eAC_callback if it was false or true when eAC calls it during onreadystatechange. Can I do that? How?
function eAC(emailData) {
if (window.XMLHttpRequest) {
httpRequest = new XMLHttpRequest();
}
if (!httpRequest) {
return false;
}
var fd = new FormData();
fd.append("email", emailData);
httpRequest.onreadystatechange = eAC_callback;
httpRequest.open('POST', "http://example.com/p_PEC.php");
httpRequest.send(fd);
}
eAC_callback returns true or false when readyState is 4 and status is 200
function eAC_callback() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var response = JSON.parse(httpRequest.responseText);
if(response.error === 0){
return true;
} else {
if(response.error === 1){
return false;
}
if(response.error === 2){
return false;
}
}
} else {
return false;
}
}
};
I want to catch the returned value of eAC_callback
Then you will have to wrap it in another function:
httpRequest.onreadystatechange = function() {
if (eAC_callback()) {
…
} else {
…
}
};
However, you will never be able to return any results computed in the asynchronous callback to the eAC function that installed the callback (long ago). See also How do I return the response from an asynchronous call? - supply a callback or return a promise.

How can I change this variable with ajax?

I'm curious as to why this isn't working, here's the code:
function Ajax(sUrl, fCallback) {
var url = sUrl || '';
var callback = fCallback || function () {};
var xmlhttp = (function () {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch (e) {
try {
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
} catch (err) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
} else {
return null;
}
}());
this.setUrl = function (newUrl) {
url = newUrl;
};
this.setCallback = function (func) {
callback = func;
};
this.request = function (method, data) {
if (xmlhttp === null) { return false; }
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4) {
callback(xmlhttp.status, xmlhttp.responseXML, xmlhttp.responseText);
}
};
data = data || '';
data = encodeURIComponent(data);
if ((/post/i).test(method)) {
xmlhttp.open('POST', url);
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlhttp.send(data);
} else {
var uri = data === '' ? url : url + '?' + data;
xmlhttp.open('GET', uri);
xmlhttp.send();
}
return true;
};
return this;
}
var ajax = new Ajax(''); // sets the url, not necessary for this demonstration
var changed = false;
function change() {
changed = true;
}
function foo() {
ajax.setCallback(change);
ajax.request();
alert(changed);
}
foo();
There is a fiddle here: http://jsfiddle.net/dTqKG/
I feel like the change function would create a closure that would indeed change the changed variable. Does anyone know what's going on?
The ajax.request(); will return before change() is called. That is the async nature of the AJAX calls, and the reason why you need the callback as opposed to just getting return value from send() method.
Other than that there might be some other issues in the code. I question why wouldn't you use one of the many AJAX frameworks readily available instead of writing your own.

ajax synchronous call problem

I have an Ajax function which looks like :
function getData(p) {
loadingImage();
p = p.replace("frame_", "");
if (window.XMLHttpRequest) {
AJAX=new XMLHttpRequest();
} else {
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX) {
var __page =encodeURIComponent(p);
AJAX.open("GET", "page.php?page="+__page, false);
AJAX.send(null);
var __data = AJAX.responseText.match(/<data>[\s\S]*?<\/data>/gmi);
if(!__data) { return false; }
return __data;
} else {
return false;
}
}
then i have very simple loading function ( an loading image must appear in center of page ) :
function loadingImage(type)
{
document.getElementById("body").innerHTML = "<div class='loading'></div>";
}
then how i call ajax function :
var loadedData = getData("home");
if(loadedData)
{
document.getElementById("body").innerHTML = loadedData;
}
else
{
document.getElementById("body").innerHTML = "Error";
}
but the loading image won't appear, it's quite simple, but i'm stuck here , how make it to show that loading image while requesting data, then to replace loading image with loaded data. Thanks
function getData(p, cb) {
loadingImage();
p = p.replace("frame_", "");
if (window.XMLHttpRequest) {
AJAX = new XMLHttpRequest();
} else {
AJAX = new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX) {
var __page = encodeURIComponent(p);
AJAX.open("GET", "page.php?page=" + __page, true);
AJAX.onreadystatechange = function(e) {
if (AJAX.readystate === 4) {
var __data = AJAX.responseText.match(/<data>[\s\S]*?<\/data>/gmi);
cb(data);
}
};
AJAX.send(null);
} else {
cb(null);
}
}
getData("home", function(loadedData) {
if (loadedData) {
document.getElementById("body").innerHTML = loadedData;
}
else {
document.getElementById("body").innerHTML = "Error";
}
});
Use async = true in the .open call.
Bind an eventhandler to readystatechange. If the readystate is 4 (LOADED) then get the data and send it to your callback.
If the AJAX fails call the callback with null or false.
In your callback get the loadedData and either render it or throw an error if there is no data.

Categories