I make APIs all the time and I'm working on one called Swerer. Swerer is an easy and efficient way to use AJAX. Now the problem is when I use Swerer.getFile("file.txt") it returns undefined instead of the content. Any help would be appreciated.
/*
Complex.js 1.0.0
Dec 14, 2017
*/
(function(){
if(!document){
throw new Error("Complex.js needs a window with a document");
}
})();
var toString = Object.prototype.toString;
// Make X
X = function(){
};
X.extend = function(){
var target = arguments[0], obj, arg = arguments;
for (var i = 0; i < arg.length; i++) {
if(toString.call(arg[i]) == "[object Boolean]"){
if(arg[i] !== false){
if(!target){
obj = [];
}else{
for(i in target){
target[i] = obj[i];
}
}
}else{
obj = [];
}
}
}
return obj;
};
// Make constructors
X.extend({
// We are going to make something called Swerer
Swerer: function(){
X.call(this);
},
isFunction: function(obj){
if(toString.call(obj) == "[object Function]"){
return true;
}
},
});
var Swerer = X.Swerer;
Swerer = {};
// Note:
// When we are refering to Swerer in a Swerer function we can use the keyword 'this'
/*
Swerer.get("file.type", function(){
func(arg);
});
*/
// Xhr (XML Http Request) is built into Swerer
(XMLHttpRequest) ? Swerer.xhr = new XMLHttpRequest() : Swerer.xhr = new ActiveXObject("Microsoft.XMLHTTP");
Swerer.getFile = function(file){
var xhttp = this.xhr, content;
if(this.readyState == 4 && this.status == 200){
content = this.responseText;
}
xhttp.open("GET", file, true);
xhttp.send();
return content;
};
If you see any problems post a jsfiddle and I'll try to fix it. Thank you!
I must admit that I only focus on the XHR part of the code, but that should look something like this:
// Xhr (XML Http Request) is built into Swerer
(XMLHttpRequest) ? Swerer.xhr = new XMLHttpRequest() : Swerer.xhr = new ActiveXObject("Microsoft.XMLHTTP");
Swerer.getFile = function(file){
var xhttp = this.xhr;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
return xhttp.responseText;
}
};
xhttp.open("GET", file, true);
xhttp.send();
};
Related
I am using AJAX GET to get a local JSON file and it does that, but once i try to return it says undefined.
ScoreHandler = function () {
this.getScores = function() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText);
//This logs object
console.log(data);
return data;
}
};
xmlhttp.open("GET", "JSON/Scores.json", true);
xmlhttp.send();
};
};
HighScores = function (scoreHandler) {
var scoreHandler = scoreHandler;
var scores = this.scoreHandler.getScores();
//This logs undefined
console.log(scores);
}
Just implement a callback for response, something like this
ScoreHandler = function () {
this.getScores = function(callback) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var data = JSON.parse(this.responseText);
//This logs object
console.log(data);
if(typeof callback === 'function')
callback(data);
//return data;
}
};
xmlhttp.open("GET", "JSON/Scores.json", true);
xmlhttp.send();
};
};
HighScores = function (scoreHandler) {
var scoreHandler = scoreHandler; //why this line use it directly
var scores = this.scoreHandler.getScores(function(data){
console.log("response", data); //you can see the data here
});
//This logs undefined
console.log(scores);
}
This is my first post here on Stack. I am trying to make a Get request which is succeeding but I am having trouble getting the responseXML into a variable for processing. I think I am supposed to be using a callback function, but I still can't get it quite right. I am hopeful that somebody can point me in the correct direction. Code below.
<script type="text/javascript">
function buildOptions() {
var data = null;
/*xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
callback.call(xhr.responseXML);
}
});*/ //This code block worked, but I couldn't figure out how to get the result back
getXML = function(callback) {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
callback(xhr.responseText);
}
xhr.open("GET", "http://URLRemoved");
xhr.setRequestHeader("authorization", "StringRemoved");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("postman-token", "TokenRemoved");
xhr.send();
}
}
function XMLCallBack(data) {
alert(data); // These two functions were the most recent attempt but I'm still missing something
}
xmlDoc = getXML(XMLCallBack); // this is supposed to start the processing of the returned XML
console.log(xmlDoc);
var campaignName = xmlDoc.getElementsByTagName('self')[0]; //XMLDoc contains a null variable when I get to this line
console.log(campaignName);
var campaigns = ["","Freshman Campaign","Sophomore Campaign","Junior Campaign","Senior Campaign"]; //Code from here and below will be changing slightly once I can get XMLDoc to be correct
var sel = document.getElementById('campaignList');
for(var i = 0; i < campaigns.length; i++) {
var opt = document.createElement('option');
opt.innerHTML = campaigns[i];
opt.value = campaigns[i];
sel.appendChild(opt);
}
}
</script>
I believe you should move open ---> send outside the onreadystatechange, like this:
getXML = function(callback) {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
callback(xhr.responseText);
}
}
xhr.open("GET", "http://URLRemoved");
xhr.setRequestHeader("authorization", "StringRemoved");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("postman-token", "TokenRemoved");
xhr.send();
}
EDIT: This code should work:
<script type="text/javascript">
function buildOptions() {
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.onreadystatechange = XMLCallBack;
xhr.open("GET", "http://URLRemoved");
xhr.setRequestHeader("authorization", "StringRemoved");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("postman-token", "TokenRemoved");
xhr.send();
function XMLCallBack() {
if (xhr.readyState == 4 && xhr.status == 200) {
xmlDoc = xhr.responseText;
var campaignName = xmlDoc.getElementsByTagName('self')[0];
var campaigns = ["","Freshman Campaign","Sophomore Campaign","Junior Campaign","Senior Campaign"];
var sel = document.getElementById('campaignList');
for(var i = 0; i < campaigns.length; i++) {
var opt = document.createElement('option');
opt.innerHTML = campaigns[i];
opt.value = campaigns[i];
sel.appendChild(opt);
}
}
}
}
</script>
I haven't tried it so I might have made some mistakes. If you want to, you can move XMLCallBack() outside of buildOptions() and use this.readyState, this.status and this.responseText instead of xhr.readyState etc..
I'm using the following code to make multiple async. calls and I need to know how many of those calls are pending for validating purposes.
function llenarComboMetodos(cell) {
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
else {
throw new Error("Las llamandas asincronas no son soportadas por este navegador.");
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status == 200 && xhr.status < 300) {
var combo = '<select name="metodos[]">';
var opciones=xhr.responseText;
combo+= opciones+"</select>";
cell.innerHTML = combo;
}
}
}
xhr.open('POST', 'includes/get_metodos.php');
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send("completar=1");
}
Is there a way to know that?
Thank you (:
You can intercept the XMLHttpRequest.send and do your counting of active calls:
var activeXhr = (function(){
var count = 0;
XMLHttpRequest.prototype.nativeSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
this.onreadystatechange = function(){
switch(this.readyState){
case 2: count++; break
case 4: count--; break
}
};
this.nativeSend(body);
};
return count;
})();
console.log(activeXhr);
EDIT: I've tried to implemented the solution, but it still doesn't work. Sorry i'm a programming idiot. Thanks for the link to the page.
In my first function databaseBOscreens i am attempting to obtain symbols of stocks according to the filter selected for a broker and/or an asset class. The function sends a request to another file which performs SELECT statement to lookup for the relevant symbols using mysqli. The result would be an array of symbols, which i then encode and subsequently parsed in this js function.
Each symbol will then go through a second process, which is my second function generatePrice() to obtain the historical prices for that particular symbol. What i'm trying to do is to loop through all symbols to generate and store the priceArr as an array in the resultArr. Sorry for being unclear.
function databaseBOscreens(broker,assetClass) {
var xhr;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
var data = "broker=" + broker + "&category=" + assetClass;
xhr.open("POST", "generateSymbol.php", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
xhr.onreadystatechange = receive_data;
function receive_data() {
if (xhr.readyState == 4 && xhr.status == 200)
{
var resultArr = JSON.parse(xhr.responseText);
var priceArr = new Array();
for(var ctr=0;ctr<resultArr.length;ctr++)
{
generatePrice(function(result,resultArr[ctr].symbol)){
priceArr[ctr] = result;
}
}
}
}
}
function generatePrice(callback,symbol) {
var xhr2;
if (window.XMLHttpRequest) {
xhr2 = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xhr2 = new ActiveXObject("Microsoft.XMLHTTP");
}
var data2 = "symbol=" + symbol;
xhr2.open("POST", "generatePrice.php", true);
xhr2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr2.send(data2);
xhr2.onreadystatechange = receive_data2;
function receive_data2() {
if (xhr2.readyState === 4)
{
if (xhr2.status === 200)
{
var priceArr = JSON.parse(xhr2.responseText);
callback(priceArr);
}
}
}
}
function receive_data() {
if (xhr.readyState == 4 && xhr.status == 200)
{
var resultArr = JSON.parse(xhr.responseText);
var priceArray = new Array();
for(var ctr=0;ctr<resultArr.length;ctr++)
{
priceArray = generatePrice(resultArr[ctr].symbol);
}
alert(priceArray.length);
}
}
My function generatePrice() returns an array, but i can't seem to store it in another array to create a multidimensional array. I've search everywhere i can't seem to get it work. Thanks in advance for any help rendered
generatePrice function:
function generatePrice(symbol) {
var xhr2;
if (window.XMLHttpRequest) {
xhr2 = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xhr2 = new ActiveXObject("Microsoft.XMLHTTP");
}
var data2 = "symbol=" + symbol;
xhr2.open("POST", "generatePrice.php", true);
xhr2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr2.send(data2);
xhr2.onreadystatechange = receive_data2;
function receive_data2() {
if (xhr2.readyState == 4 && xhr2.status == 200)
{
var priceArr = JSON.parse(xhr2.responseText);
return priceArr;
}
}
}
My function generatePrice() returns an array,
No it doesn't, it returns undefined. XHR is asynchronous, see How do I return the response from an asynchronous call?.
priceArray = generatePrice(resultArr[ctr].symbol);
I can't seem to store it in another array
You didn't attempt to do so, you just stored the result of every call in the priceArray variable - instead of in a property of the array. Use
priceArray[ctr] = generatePrice(resultArr[ctr].symbol);
// or
priceArray.push( generatePrice(resultArr[ctr].symbol) );
I have defined one root object that I want to use as "namespace" for the rest of my classes. Inside this root object i have two classes - TOOLS and PRESENTATION. In PRESENTATION class i need to call one of public methods from TOOLS. As I can tell after playing with console.log in every step of execution of this code problem is that return xhr.responseText don't pass anything back to tools.getData(configPath) and I'm ending up with undefined in console.log(pres.config).
CODE:
// Create Namespace
var AppSpace = AppSpace || {};
// Class and Constructor
AppSpace.Tools = function() {
//public methodts
this.test = function(arg) {
return arg
}
this.getData = function(path) {
var xhr = new XMLHttpRequest();
xhr.open('GET', path, false);
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status !== 0 && xhr.status !== 200) {
if (xhr.status === 400) {
console.log("Could not locate " + path);
} else {
console.error("app.getData " + path + " HTTP error: " + xhr.status);
}
return;
}
return xhr.responseText;
};
xhr.send();
}
}
// Class and Constructor
AppSpace.Presentation = function(initName, initfPath){
//private properties
var configPath = initfPath || 'config.json';
var configData = null;
var name = initName || 'Unnamed Presentation';
//private methods
var getConfigContent = function() {
return tools.getData(configPath);
}
var getConfigData = function() {
return JSON.parse(getConfigContent);
}
//public methodts
//public properties
this.name = null;
this.config = null;
this.debug = null;
//logic
this.name = name;
this.config = getConfigContent();
}
//execution
var tools = new AppSpace.Tools();
var pres = new AppSpace.Presentation('Some Name');
pres.debug = tools.test('value passed')
console.log(pres.debug);
console.log(pres.config);
console.log(pres.name);
Output in browsers console is:
value passed js-oop.dev:99
**undefined js-oop.dev:100**
Some Name js-oop.dev:101
Can anyone give little advice on this? TIA.
I mean that if you want that your ajax control return some datas directly from your function you have to use a synchronous method. Without it, datas will be sent from the onreadystatechange event.
Here is a sample how to create a synchronous call for ajax
// Create Namespace
var AppSpace = AppSpace || {};
// Class and Constructor
AppSpace.Tools = function() {
//public methodts
this.test = function(arg) {
return arg
}
this.getData = function(path) {
var xhr_object= new XMLHttpRequest();
// Start synchronous ajax
xhr_object.open("GET", path, false);
xhr_object.send(null);
// Return data
return xhr_object.responseText;
}
}
// Class and Constructor
AppSpace.Presentation = function(initName, initfPath){
//private properties
var configPath = initfPath || 'config.json';
var configData = null;
var name = initName || 'Unnamed Presentation';
//private methods
var getConfigContent = function() {
return tools.getData(configPath);
}
var getConfigData = function() {
return JSON.parse(getConfigContent);
}
//public methodts
//public properties
this.name = null;
this.config = null;
this.debug = null;
//logic
this.name = name;
this.config = getConfigContent();
}
//execution
var tools = new AppSpace.Tools();
var pres = new AppSpace.Presentation('Some Name');
pres.debug = tools.test('value passed')
console.log(pres.debug);
console.log(pres.config);
console.log(pres.name);
First, in this code:
this.getData = function(path) {
var xhr = new XMLHttpRequest();
xhr.open('GET', path, false);
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status !== 0 && xhr.status !== 200) {
if (xhr.status === 400) {
console.log("Could not locate " + path);
} else {
console.error("app.getData " + path + " HTTP error: " + xhr.status);
}
return;
}
return xhr.responseText;
};
xhr.send();
}
return xhr.responseText; will not work. It is inside handler function and value will be returned from xhr.onreadystatechange, but not from getData, so you may do something like this:
this.getData = function(path) {
var res;
var xhr = new XMLHttpRequest();
xhr.open('GET', path, false);
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status !== 0 && xhr.status !== 200) {
if (xhr.status === 400) {
console.log("Could not locate " + path);
} else {
console.error("app.getData " + path + " HTTP error: " + xhr.status);
}
return;
}
res = xhr.responseText;
};
xhr.send();
return res;
}
Also, this should be like next (you are trying to parse an function, not what it returns)
var getConfigData = function() {
return JSON.parse(getConfigContent());
}
If you'd like to keep it asynchrous you can do something like this. I'd either remove the dest and prop parameters, or the callback, depending on your needs.
this.getData = function(path, dest, prop, callback) {
callback = callback || null;
var xhr = new XMLHttpRequest();
xhr.open('GET', path, false);
xhr.onreadystatechange = function() {
if (xhr.readyState !== 4) return;
if (xhr.status !== 0 && xhr.status !== 200) {
/* ... */
}
dest[prop] = xhr.responseText;
if (Callback) callback(xhr.responseText);
};
xhr.send();
}
//private methods
var getConfigContent = function() {
return tools.getData(configPath, this, 'config', );
}