I'm trying to make a Javascript function that gets two arguments, an URL and a data, posts it to a PHP and returns the server's response without jQuery or any library. (Source)
function post(URL, data) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('POST', URL, true);
req.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
} else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error('Network Error'));
};
req.send(data);
});
}
<?php
if ( isset($_POST['data']) ) {
echo json_encode(array("Hey {$_POST['data']}" ));
} else {
echo json_encode(array("Error"));
}
?>
So far so good, here's how I'm handling it.
function handle(URL, data) {
post(URL, data).then(function(response) {
return response;
}, function(error) {
return error;
});
}
However, this always returns undefined. Interestingly, if I try to console.log(response) it works fine.
I want to be able to do such things like alert(handle(URL, data));
Is this impossible? If yes how could I get around it?
I ended up reworking my script to use callback instead.
var AJAX = {
get: function(a, b) {
var c = new XMLHttpRequest();
c.onreadystatechange = function() {
if (c.readyState == 4 && c.status == 200) {
b(c.responseText);
}
};
c.open('GET', a, true);
c.send();
},
post: function(a, b, d) {
var c = new XMLHttpRequest();
c.onreadystatechange = function() {
if (c.readyState == 4 && c.status == 200) {
d(c.responseText);
}
};
c.open('POST', a, true);
c.setRequestHeader('Content-type',
'application/x-www-form-urlencoded');
c.send(b);
}
};
This is how you call it: AJAX.get('text.txt', function doSomething(what){console.log(what)});
Related
I use an XMLHttpRequest inside a Promise. Because the server sometimes is idle, I would like to do 3 attemps when there is an error.
However, doing like below raise the Object state must be opened error on line xhr.send() in the function sendData(). Why?
I think the xhr is already opened. What would be the proper way to achieve this?
function _callService(url, postData) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
var attempts = 0;
xhr.open("POST", url);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.response);
}
}
};
xhr.addEventListener("error", onXhrError);
function sendData() {
//here I get the Object state must be opened when this is called from onXhrError listener
xhr.send(postData);
};
function onXhrError() {
console.log("onXhrError");
if (attempts < 3) {
attempts += 1;
sendData();
} else {
reject("OnXhrError")
}
};
sendData();
});
Schedule _callService(url, postData, attempts) to be called again instead of sendData(), see multiple, sequential fetch() Promise.
function callService(attempts) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (attempts < 3)
reject(++attempts)
else
resolve("done");
}, Math.floor(Math.random() * 1200))
}).catch(function(err) {
throw err
})
}
function request(n) {
return callService(n)
.then(function(data) {
console.log(data);
return data
})
.catch(function(err) {
console.log(err);
return typeof err === "number" && err < 3 ? request(err) : typeof err !== "number" ? new Error(err) : "requested " + err + " times";
})
}
request(0)
.then(function(done) {
console.log("done:", done)
})
.catch(function(err) {
console.log(err)
})
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
}
});
http://kiwilocals.com.au/dev/
Hello, here is the ajax requests on a category in the middle of the page under the banner. Work everywhere, in addition to all versions of IE.
I checked the developer's tools, a query gives the correct structure, but nothing on the loading icon does not appear after loading. In what may be the reason? Thank you.
function scat(th) {
wait_loading('sub_lst');
if (request = create_request()) {
request.open("GET", "get_subcat.php?id=" + th + "&site=1", true);
request.onreadystatechange = function () {
//alert(request);
if (this.status == 200) {
if (this.readyState == 4) {
var doc3 = document.getElementById('sub_lst');
//alert(doc3);
doc3.innerHTML = this.responseText;
if (!scroll_start) {
$('.sub_scroll').jScrollPane({
animateScroll: true
});
$('.hidden_control').show();
scroll_start = true;
}
}
}
}
request.send(null);
}
}
function create_request() {
var request = false;
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
try {
request = new XMLHttpRequest();
} catch (e3) {
request = false;
}
}
}
if (!request) {
alert("Невозможно выполнить Ajax запрос.");
return false;
} else return request;
}
function wait_loading(el_id) {
document.getElementById(el_id).innerHTML = "<center><img style=\"padding-top: 60px;\" width=\"64\" height=\"64\" src=\"images/loading.gif\"></center>";
}
The problem is with your use of 'this' in the readstatechange event.
Give this a shot.
if(request = create_request()) {
request.open("GET", "get_subcat.php?id="+th+"&site=1", true);
request.onreadystatechange = function() {
if(request.status == 200) {
if( request.readyState == 4 ) {
var doc3 = document.getElementById('sub_lst');
doc3.innerHTML=request.responseText;
if(!scroll_start) {
$('.sub_scroll').jScrollPane({animateScroll: true});
$('.hidden_control').show();
scroll_start=true;
}
}
}
}
request.send(null);
}
But one question... you use jQuery throughout your code, except for this. Why not use:
$('#sub_lst').load("get_subcat.php?id="+th+"&site=1", function(){
if(!scroll_start) {
$('.sub_scroll').jScrollPane({animateScroll: true});
$('.hidden_control').show();
scroll_start=true;
}
});
I'm working on the project where I (sadly) cannot use jQuery. And I need to do something which is simple in jQuery but I cannot do it in pure JavaScript. So, I need to run one ajax request using a response form another one. In jQuery it will look like:
$.get("date.php", "", function(data) {
var date=data;
$("#date").load("doku.php?id="+date.replace(" ", "_")+" #to_display", function() {
$(document.createElement("strong")).html(""+date+":").prependTo($(this));
});
});
And this is my code in pure JS which isn't working:
if (window.XMLHttpRequest)
{
ObiektXMLHttp = new XMLHttpRequest();
} else if (window.ActiveXObject)
{
ObiektXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if(ObiektXMLHttp)
{
ObiektXMLHttp.open("GET", "date.php");
ObiektXMLHttp.onreadystatechange = function()
{
if (ObiektXMLHttp.readyState == 4)
{
var date = ObiektXMLHttp.responseText;
if (window.XMLHttpRequest)
{
ObiektXMLHttp = new XMLHttpRequest();
} else if (window.ActiveXObject)
{
ObiektXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
ObiektXMLHttp.open("GET", "doku.php?id="+date.replace(" ", "_"));
ObiektXMLHttp.onreadystatechange = function()
{
if (ObiektXMLHttp.readyState == 4)
{
alert(ObiektXMLHttp.responseText);
}
}
}
}
ObiektXMLHttp.send(null);
}
What am I doing worng?
You forgot to call ObiektXMLHttp.send(null); on second case:
//....
ObiektXMLHttp.open("GET", "doku.php?id="+date.replace(" ", "_"));
ObiektXMLHttp.onreadystatechange = function() {
if (ObiektXMLHttp.readyState == 4)
{
alert(ObiektXMLHttp.responseText);
}
};
//Here
ObiektXMLHttp.send(null);
How about something like this (naive prototype):
// xhr object def
var xhr = {
obj: function() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
throw new Error("can't init xhr object");
},
get: function(url, fn) {
var xhr = this.obj();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
fn(xhr.responseText);
}
};
xhr.open("GET", url);
xhr.send(null);
}
};
// implementation
xhr.get("date.php", function(data){
xhr.get("doku.php?id=" + data.replace(" ", "_"), function(data){
alert(data);
});
});
It's not clear what you got wrong (can you tell us?), but I'd suggest to rely on some helper function like this:
function xhrGet(url, callback) {
if (window.XMLHttpRequest)
var xhr = new XMLHttpRequest();
else if (window.ActiveXObject)
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
if (!xhr) return;
xhr.open("GET", url);
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (typeof callback === "function") callback(xhr);
};
xhr.send(null);
return xhr;
}
So all you have to do is to use this function:
xhrGet("date.php", function(x1) {
xhrGet("doku.php?id=" + date.replace(" ", "_"), function(x2) {
// do stuff
// x1 and x2 are respectively the XHR object of the two requests
});
});
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.