Increment variable in constructor function (JS) - javascript

I am fetching the data from 2 different APIs and I wrote a constructor function that will start XMLHttpRequest based on the new instance of the object creation (if it makes any sense...). Once the data is fetched and parsed I want to save it into different named variables. For instance: trial1data, trial2data. At the minute the new instances of the objects overwrite the data variable. Code below:
var api = "http://www.filltext.com/?rows=10&fname={firstName}&lname={lastName}&pretty=true";
var api2 = "http://www.filltext.com/?rows=10&fname={firstName}&lname={lastName}&tel={phone|format}&address={streetAddress}&city={city}&state={usState|abbr}&zip={zip}&pretty=true";
function FetchData(apiType) {
var r = new XMLHttpRequest();
this.apiType = apiType;
this.request = function() {
r.open("GET", apiType, true);
r.onload = function() {
var data = JSON.parse(r.responseText);
}
r.send(null);
}
}
trial1 = new FetchData (api);
trial1.request();
trial2 = new FetchData (api2);
trial2.request();
Thanks for the XMLHttpRequest tip, but the issue was to save each data into separate variables such as trial1data and trial2data (or anything else that has got a meaning and I can re-use later on), based on how many new objects I will create.

Your var r = new XMLHttpRequest(); is common.
You need to move it inside the function to create separate request everytime the constructor function is called.
function FetchData(apiType) {
this.apiType = apiType;
this.request = function() {
var r = new XMLHttpRequest();
r.open("GET", apiType, true);
r.onload = function() {
var data = JSON.parse(r.responseText);
console.log(data);
}
r.send(null);
}
}

You should put the request object creation inside the constructor:
function FetchData(apiType) {
var r = new XMLHttpRequest();
this.apiType = apiType;
this.done = new Promise( res => {
r.onload = function() {
res(JSON.parse(r.responseText) );
};
});
this.request = function() {
r.open("GET", apiType, true);
r.send(null);
};
}
So you can do:
const req = new FetchData("whatever");
req.request();
req.done.then(console.log);

Create new instance on var r = new XMLHttpRequest(); inside of constructor, or as a better approach, make it an argument for a constructor and inject new XMLHttpRequets object for each.
To answer the second part of your question, you could store response data in object's property and access it directly or getter interface. So instead of
r.onload = function() {
var data = JSON.parse(r.responseText);
}
Do something like:
function FetchData(apiType) {
var self = this;
this.apiType = apiType;
this.request = function() {
var r = new XMLHttpRequest();
return new Promise(function(resolve, reject) {
r.open("GET", apiType, true);
r.onload = function() {
self.data = JSON.parse(r.responseText);
resolve(self.data);
}
r.send(null);
}
}
Then
trial1 = new FetchData (api);
var trial1resp;
trial1.request().then(function(data) {
trial1resp = data;
}
The last assignment is just to show how is response stored. You must handle async processess to achieve your goal.
You could read little bit more about promisses and how to handle xhr async tasks here https://developers.google.com/web/fundamentals/primers/promises

Related

adjust onload function to be used with async/await [duplicate]

This question already has answers here:
How do I promisify native XHR?
(6 answers)
Closed 3 months ago.
I'm working on converting an xlsx I get from a URL to a JSON object in the Browser.
This answer works --> https://stackoverflow.com/a/52237535/5079799
But, I can't get the code to wait for the reponse. All the answers online seem to be about images and/or using an input filereader, but I'm fetching a URL.
How I can wrap this all in a function that says:
Get XLSX from URL
Convert to JSON
Return JSON
Here is what I've been messing with so far, but it always ends with the outside variables unset but the inside works correctly.
async function Outside_Test(){
var reso = await Get_JSON()
console.log('reso_out')
console.log(reso)
}
async function Get_JSON() {
var url = "http://myspreadsheet.xlsx"
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
//oReq.onload =
return oReq.send()
.then(function (oReq) {
var arraybuffer = oReq.response;
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var workbook = XLSX.read(bstr, {
type: "binary"
});
/* DO SOMETHING WITH workbook HERE */
var first_sheet_name = workbook.SheetNames[0];
/* Get worksheet */
var worksheet = workbook.Sheets[first_sheet_name];
var reso = (XLSX.utils.sheet_to_json(worksheet, {
raw: true
}));
console.log('inside-reso')
return reso
})
}
You'll want to return a Promise from Get_JSON that resolves when .onload is called
something like
function Get_JSON() {
return new Promise((resolve, reject) => {
var url = "http://myspreadsheet.xlsx"
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = function () {
/* convert data to binary string */
/* Call XLSX */
/* DO SOMETHING WITH workbook HERE */
/* Get worksheet */
console.log('inside-reso')
resolve(reso);
});
oReq.onerror = reject;
oReq.send() ;
});
}
Note: no need for Get_JSON to be async ... since you never need to await
Another alternative I guess is
async function Get_JSON() {
const arrayBuffer = await new Promise((resolve, reject) => {
var url = "http://myspreadsheet.xlsx"
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = () => resolve(oReq.response);
oReq.onerror = reject;
oReq.send();
});
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
// ...
/* Call XLSX */
// ...
/* DO SOMETHING WITH workbook HERE */
// ...
/* Get worksheet */
// ...
return reso;
}
I kinda like this way, using async/await makes it clear this will return a Promise

XMLHttpRequest on load in saveback to calling object

I'm trying to load in many json files for a HTML5 game that will serve as sprite sheets. Previously I've did this synchronously but my new goal is to do this asynchronously.
I have run into a problem though where I'm trying to saving back to the calling object. This is so the information loaded can be used later and so a flag (loaded) can be set so the system knows when a resource has been loaded. Below is my XMLHttpRequest code. I have substituted "spritesheet" for what ever the call should be to save back to the parent.
function SpriteSheet(filename)
{
var tmpFileName = "json/" + filename;
this.loaded = false;
var xhr = new XMLHttpRequest();
xhr.open("GET",tmpFileName,true);
xhr.onload = function(event){
var parsed = JSON.parse(this.responseText);
"spritesheet".img=new Image();
"spritesheet".img.src = "imgs/" + parsed["imgLoc"];
"spritesheet".animations = parsed["animations"];
"spritesheet".sprites = parsed["sprites"];
"spritesheet".loaded = true;
};
xhr.send();
}
Can somebody inform me how I can save back to the the parent or if this is completely the wrong approach can they point me in the direction of a solution.
I found that by creating a var in the 'class' that is a reference to the object and using it in the onload function works, for example:
function SpriteSheet(filename)
{
var tmpFileName = "json/" + filename;
this.loaded = false;
var caller = this;
var xhr = new XMLHttpRequest();
xhr.open("GET",tmpFileName,true);
xhr.onload = function(event){
var parsed = JSON.parse(this.responseText);
caller.img=new Image();
caller.img.src = "imgs/" + parsed["imgLoc"];
caller.animations = parsed["animations"];
caller.sprites = parsed["sprites"];
caller.loaded = true;
};
xhr.send();
}

acces value outside of closure to extend wavesurfer.js lib

I have 2 functions here: load recieves a path to an mp3 and count is the number of tracks being loaded in. When for loop reaches the last track arraybufferList contains an array of 'arraybuffer' of all the songs. This is then passed on to the loadData function which uses an webaudioapi function 'decodeAudioData' to decode all the information and put everything inside an "currentBuffer". However outside of the closure the "currentBuffer" seems to vanish (in my google chrome debugger).
I'm trying to use the wavesurfer.js library and extend it to multiple tracks.
load: function (src,count) {
var my = this;
var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
console.log("loading mp3 & putting inside arraybufferList");
arraybufferList.push(xhr.response);
if (arraybufferList.length==count){
console.log(arraybufferList);
for (var i=0; i<arraybufferList.length; i++){
my.backend.loadData(
arraybufferList[i],
playList[i].draw.bind(playList[i])
);
console.log(playList);
//playList.push(my);
}
console.log(playList);
}
};
xhr.open('GET', src, true);
xhr.send();
},
loadData: function (audioData, cb) {
var my = this;
this.pause();
this.ac.decodeAudioData(
audioData,
function (buffer) {
my.currentBuffer = buffer;
my.lastStart = 0;
my.lastPause = 0;
my.startTime = null;
cb(buffer);
},
Error
);
},
At the beginning for each audio file an object is created where the information from loadData should go into
var WaveSurfer = {
init: function (params) {
var my = this;
var backend = WaveSurfer.Audio;
if (!params.predrawn) {
backend = WaveSurfer.WebAudio;
}
this.backend = Object.create(backend);
this.backend.init(params);
this.drawer = Object.create(WaveSurfer.Drawer);
this.drawer.init(params);
this.backend.bindUpdate(function () {
my.onAudioProcess();
});
this.bindClick(params.canvas, function (percents) {
my.playAt(percents);
});
playList.push(my);
},
some essential code: ac: new (window.AudioContext || window.webkitAudioCont

How to prevent Ajax caching

I'm created this class to fetch a file from web to check for new version using Ajax.
This code run on a Windows gadget, on IE8. But I'm having trouble because of the cache.
Is there a way to fix this Ajax class to disable cache?
PS: I don't use any library or frameworks.
var ClassAjax = function() {
this.data = null;
var that = this;
this.get = function(url, send) {
var ajax = new function ObjAjax() {
try{ return new XMLHttpRequest(); }
catch(e){try{ return new ActiveXObject("Msxml2.XMLHTTP"); }
catch(e){ return new ActiveXObject("Microsoft.XMLHTTP"); }}
return null;
}
ajax.onreadystatechange = function() {
if(ajax.readyState == 1) { that.onLoading(); }
if(ajax.readyState == 4) { that.data=ajax.responseText; that.onCompleted(that.data); }
}
ajax.open("GET", url, true);
ajax.send(send);
};
this.onLoading = function() {
//function called when connection was opened
};
this.onCompleted = function(data) {
//function called when download was completed
};
}
var request = new ClassAjax();
request.onCompleted = function(data) { alert(data); }
request.get('http://exemple.com/lastversion.html', null);
You can pass the current timestamp as a variable in the url, like this :
var timestamp = new Date().getTime();
ajax.open("GET", url+'?ts='+timestamp, true);
Also, you can force the page to be reloaded on server-side, using the proper headers

AJAX with callback functions

I am having trouble access data within an ajax connection. Not sure what is wrong with my code. It seems as though it never reaches the 2nd function. Any ideas?
function fetchgps(callback)
{
var url = "http://www.instamapper.com/api?action=getPositions&key=584014439054448247";
var myRequest = new XMLHttpRequest();
myRequest.onload = function(e) {xml_loaded(e, myRequest, callback);}
myRequest.open("GET", url);
myRequest.setRequestHeader("Cache-Control", "no-cache");
myRequest.setRequestHeader("wx", "385");
myRequest.send(null);
return myRequest;
}
function xml_loaded(event, request, callback)
{
if (request.responseText){
var obj = {error:false, errorString:null}
var data = myRequest.responseText;
collected=data.split(","); //parses the data delimited by comma and put data into array
obj.latitude = collected[4];
obj.longitude = collected[5];
callback(obj);
}
else
{
callback ({error:true, errorString:"XML request failed. no responseXML"}); //Could be any number of things..
}
}
function dealwithgps(obj)
{
lat = obj.latitude;
lon = obj.longitude;
document.write(lon);
document.write(lat);
}
fetchgps(dealwithgps);
Thats request.onreadystatechange instead of request.onload
function fetchgps(callback)
{
var url =
"http://www.instamapper.com/api?action=getPositions&key=584014439054448247";
var myRequest = new XMLHttpRequest();
// myRequest.onload = function(e) {xml_loaded(e, myRequest, callback);}
myRequest.onraedystatechange = function() { //onraedystatechange instead of onload!!
xml_loaded(myRequest, callback);
}
myRequest.open("GET", url);
myRequest.setRequestHeader("Cache-Control", "no-cache");
myRequest.setRequestHeader("wx", "385");
myRequest.send(null);
return myRequest;
}
function xml_loaded(request, callback) {
if(request.readyState === 4) {
//... only then do your processing
}
}

Categories

Resources