push function with javascript doesn't work in this place - javascript

var members = ['herpaderpus', 'turtles_head', 'nubstep_rs', 'ardens_fide', 'newending', 'pve_bros', 'rsphilippe', 'pureismwars', 'smap51', 'iprimal_rs', 'im_mr_bloo', 'mrknowles100', 'aikohero', 'cowsbelieve', 'dombo_12', 'diovista', 'mrpixels17'];
var memberData = [];
$.each(members, function(index, member) {
$.getJSON('https://api.twitch.tv/kraken/users/' + member + '?callback=?', function(d) {
if(d.status == 404) {}
else {
var data = [];
data[0] = member;
data[1] = d.display_name;
memberData.push(data[0]);
$.getJSON('https://api.twitch.tv/kraken/streams/' + data[0] + '?callback=?', function(d) {
if(d.stream != null) {
$( "#player" ).append( "<img src='http://pso-clan.com/twitch/lib/images/online.png'>" + "<a target='_blank' href='http://www.twitch.tv/" + data[0] + "'>" + data[1] + "</a>" + " - Viewers: " + d.stream.viewers + "<br>" );
}
else {
$( "#offline" ).append( "<img src='http://pso-clan.com/twitch/lib/images/offline.png'>" + "<a target='_blank' href='http://www.twitch.tv/" + data[0] + "'>" + data[1] + "</a> - Offline<br>" );
}
});
}
});
}); alert(memberData[0]);
I don't seem to be able to call
memberData.push(data[0]);
in the place where it's right now, the alert just show undefined. Why doesn't it properly push the member to the memberData array?

You're actually incorrect - where you're using .push() is just fine (in the callback of your first $.getJSON() request).
Where you're alerting it, however is not, because this is an asynchronous request, whereby the alert occurs before the first ajax request is complete.
Take a look at the console output here: http://jsfiddle.net/remus/spSxE/ -- you'll see that undefined appears before any of the array push logging.
Options:
Rewrite your method to use parallel ajax requests like the solution here
Write the necessary DOM update functions (or whatever you're doing with the results) into the callback of each ajax request so that it is updated after each call completes.

Related

Async functions within typeaheadjs

This function works within typeahead.js context,
i use lodash request-promise and cheerio
to grab/parse/organize my data.
console.log shows every variables as it should be.
but with this line :
return '<p>' + img + data.name + ' - ' + getProviders(data) + '</p>'
i get the following error:
Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
I'm not sure what's happening, this might have something to do with typeahead.js trying to happend an invalid (because incomplete yet) DOM element.
PS: let img = $(selector).attr('src'); is intended (it stores the src attribute as a string)
PS2: if i ommit img it works:
return '<p>' + data.name + ' - ' + getProviders(data) + </p>'
function(data) {
let imgProviders = _.keys(data.url).map((r) => {
return {[r]: data.url[r]};
});
let url = imgProviders[0][_.keys(imgProviders[0])[0]].replace(/\/$/, '');
let selector = _.find(sites, {
providerName: _.keys(imgProviders[0])[0]
}).coverIMG;
let body = request.get(url, (err, res, html) => {
$ = cheerio.load(html);
// the variable that is messing with me
let img = $(selector).attr('src');
// works fine when console.log()
console.log(img, data.name, getProviders(data));
return '<p>' + img + data.name + ' - ' + getProviders(data) + '</p>';
});
}

jQuery get an Array from json file

I need to get an array from a json file and I have no idea how to do it.
Here's the code I want to get the array from:
$.getJSON('saveGames/userID' + userID + '_SAVEALPHA.json', function(data) {
console.log("Save data from: userID" + userID + "_SAVEALPHA.json: " + data);
var testVar = jQuery.parseJSON(data);
var pokemonAryTest = testVar[0].pokemon;
pokemonAry = [pokemonAryTest];
console.log("loaded players Pokemon: " + pokemonAry);
console.log(pokemonAry[0])
});
I have tried to change the index of pokemonAry to 1 and it returns undefined. And when I keep the index the same, it returns ["Pikachu, Charmander"] so I think its acting like as if it's a string.
Here's the .json:
"[{\"userID\":\"1\",\"saveName\":\"g\",\"pokemon\":[\"Pikachu, Charmander\"]}]"
When you are using getJSON() method no need to parse JSON data, jQuery take care of it. :)
$.getJSON('saveGames/userID' + userID + '_SAVEALPHA.json', function(data) {
console.log("Save data from: userID" + userID + "_SAVEALPHA.json: " + data);
var pokemonAry = data[0].pokemon;
console.log("loaded players Pokemon: " + pokemonAry);
console.log(pokemonAry[0])
});

Combine data from different URLs in ajax

I have one ajax request which i use to extract data from API, and create a table from the extracted data. Now i need to do the same, but to extract the data from two different URLs and merge is to the same table (retTable).
Here is my current code (one ajax request):
$.ajax(
{
url : '/url/status',
type: "GET",
success:function(data, textStatus, jqXHR)
{
theRows = extract_status_data(data)
},
error: function(jqXHR, textStatus, errorThrown)
{
alert('error')
}
});
}
function extract_status_data(jsonDataRaw){
jsonResultSect = jsonDataRaw['result']
retTable = ""
for( key in jsonResultSect){
statusParam = jsonResultSect[key]
a = statusParam['a']
b = statusParam['b']
c = statusParam['c']
d = statusParam['d']
e = statusParam['e']
retTable += "<tr><td>" + dropDownList(key) + "</td><td>" + key + "</td><td>" + a + "</td><td>" + b + "</td><td>" + c + "</td><td>" + d + "</td><td>" + e + "</td></tr>"
}
return retTable
}
How would be correct to combine the data from two different URLs? Please advise.
I can't hammer out a really robust solution right now, but here is what I came up with: https://jsfiddle.net/heejse8h/
Basically the principal is that you place all the URLs in an array and keep a flag variable incrementing for every url you pull from. This might look like this:
urls = [
'/url/status',
'/url/status2'
];
var i = 0;
Then when you execute the AJAX, you'll want to store that in some array
var result = [];
For my AJAX call in the jsfiddle, I used this basic structure
$.ajax({
url : urls[i],
type: "GET",
success: function(data) {
// simplified example of storing the results
// the example code from the fiddle is more
// involved.
result[key].push(data);
if(urls[++i] !== undefined){
// if there is another URL, use the same
// ajax object (using `this`), extend it,
// changing only the URL, and call it.
// the important part is that the `this`
// object has a reference to the currently
// executing `success` method.
$.ajax($.extend(this, {url: urls[i]}));
} else {
// otherwise, we're at the end of our URLs
// and we can focus on final formatting and
// display of the data.
for( key in result ){
$('#mytable').append("<tr><td>" + dropDownList(key) + "</td><td>" + key + "</td>" + result[key].join('') + "</tr>");
}
}
}
});
In the end I would have liked to flesh this out and use the DOM API to actually create nodes rather than constant concatenation, but this solution already diverges from the original code quite a bit. You might want to consider creating a function that parses an object rather than relies on concatenation.

AJAX acting in a multi threaded manner

I understand that JavaScript is single threaded (as explained in this question: If Javascript is not multithreaded, is there any reason to implement asynchronous Ajax Queuing?), however I am trying to understand how this applies to the application I have developed. Please see the code below:
function GetSQLTable() {
var str = $("#<%=fieldDatabaseReferences.ClientID%>")[0].value
var res = str.split(",");
$("#LoadingImage").show();
$("#LoadingImage2").show();
for (var i = 0; i < res.length; i++) {
(function (i, res) {
setTimeout(function () {
GetSQLTable2(i, res.length, res)
}, 0);
})(i, res);
}
}
function GetSQLTable2(i,reslength,res) {
//if (i == 0)
//{
// var start = new Date().getTime();
//}
var div = document.createElement('div');
div.id = "div" + i
document.getElementById('info_div').appendChild(div);
var PossiblesPage = false;
$.ajax({
type: "POST",
url: "PrimaryNominalAjax.aspx/GetSQLTable",
data: '{username: "' + $("#<%=fieldUserName.ClientID%>")[0].value + '", terminalname: "' + $("#<%=fieldTerminalName.ClientID%>")[0].value + '", terminalip: "' + $("#<%=fieldTerminalIP.ClientID%>")[0].value + '", mappingid: "' + res[i] + '", usergroup: "' + $("#<%=fieldUserGroup.ClientID%>")[0].value + '", usn: "' + $("#<%=fieldUSN.ClientID%>")[0].value + '", requester: "' + $("#<%=fieldRequester.ClientID%>")[0].value + '", reason: "' + $("#<%=fieldReason.ClientID%>")[0].value + '", rrd: "' + $("#<%=fieldRRD.ClientID%>")[0].value + '", review: "' + $("#<%=fieldReview.ClientID%>")[0].value + '", possibles: "' + PossiblesPage + '",linkno: "", urn1: "", urn2: ""}',
contentType: "application/json; charset=utf-8",
timeout: 80000000,
dataType: "json",
success: OnSuccess(i, reslength),
error: OnError,
failure: function (response) {
alert('there was an error loading the webpage')
}
});
}
fieldDatabaseReferences is populated on the server side. The AJAX connects to multiple local databases (up to 30) and puts the information on the screen as and when it is ready.
The calls to the various database servers are asynchronous. Surely this has a multi threaded effect?
JavaScript is single threaded. When asynchronous events occur, they are are pushed into a queue waiting to be executed until the thread is idle. Consider the following example:
var run = true;
var brk = Date.now() + 5000; // five seconds from now
setTimeout(function(){
run = false; // set the run variable to false _asynchronously_
}, 1000); // after one second
while(run && Date.now() < brk); // loop while both conditions are true
console.log("run:", run); // logs run: true (which was the initial value)
When do you suppose the loop will terminate? One second? No it would run indefinitely (if Date.now check was not there). The fact that the value logged in console is true confirms that the timeout is not fired. It is in the queue, waiting for the var run = true...console.log() block to terminate.
As for your example, the order of execution would be:
/* note: no two functions execute at same time */
GetSQLTable();
/* functions scheduled via setTimeout execute one by one */
GetSQLTable2(0, ...);
GetSQLTable2(1, ...);
GetSQLTable2(2, ...);
/* AJAX requests complete one by one, not necessarily in the order they started */
OnSuccess(2);
OnSuccess(0);
/* JavaScript thread could be idle during callbacks */
OnSuccess(1);
References:
http://ejohn.org/blog/how-javascript-timers-work/
http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/

Variable without value inside callback function

Im having a strange problem with the following code:
function getTrxData(trx,inputPar,outputPar,callback) {
var retorno = {};
var URL = '/XMII/Runner?Transaction=' + trx;
var params = "";
for(key in inputPar)
params = params + "&" + key + "=" + inputPar[key];
if(!outputPar)
outputPar = "*";
if(params)
URL = URL + params;
URL = URL + '&OutputParameter=' + outputPar;
$.ajax({
type: "GET",
url: URL,
async: true,
success: function(data){
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
},
error: function(jqXHR, textStatus, errorThrown){
retorno.tipo = 'E'; // Error
retorno.mensaje = "Error: " + textStatus;
callback(retorno);
}
});
}
function crearSelect(trx,inputPar,outputPar,selectID,campoTextoXX,campoValor,valorDefault,callback2) {
// At this point campoTextoXX exists and has a value
getTrxData(trx,inputPar,outputPar,function(retorno2) {
// At this point campoTextoXX is an object equal to callback2
if(retorno2.tipo == 'E') {
callback2(retorno2);
return false;
}
var options = "";
var selected = "";
$.each(retorno2.datos.Rowset.Row, function(k,v) {
if(valorDefault == v[campoValor]) {
selected = " selected='selected'";
} else {
selected = "";
}
options = options + "<option value='" + v[campoValor] + selected "'>";
options = options + v[campoTextoXX];
options = options + "</option>";
});
$("#" + selectID + " > option").remove();
$("#" + selectID).append(options);
callback2(retorno2);
});
}
And the call is like this:
crearSelect("Default/pruebas_frarv01/trxTest",{letra: 'V'},"*",'selectID',"CustomerID",'OrderID','',function(retorno) {
alert(retorno.tipo + ": " + retorno.mensaje);
});
The problem is that campoTextoXX and campoValor dont get any value inside the callback function. Also, debugging in Chrome shows me that campoTextoXX has the value of the callers callback function:
alert(retorno.tipo + ": " + retorno.mensaje);
I dont know what to do next.
Any ideas?
Thx
You might find it easier to mange the callback chain by exploiting $.ajax's ability to behave as a jQuery Deferred.
This allows us very simply to specify the "success" and "error" behaviour in the guise of request.done(...) and request.fail(...) at the point where getTrxData is called rather than inside getTrxData - hence the callback chain is (ostensibly) one level less deep.
function getTrxData(trx, inputPar, outputPar) {
inputPar.Transaction = trx;
inputPar.OutputParameter = (outputPar || '*');
return $.ajax({
url: '/XMII/Runner?' + $.param(inputPar)
});
}
function makeOptions(obj, selectID, campoTextoXX, campoValor, valorDefault) {
var $option, selected, $select = $("#" + selectID);
$("#" + selectID + " > option").remove();
$.each(obj.datos.Rowset.Row, function(k, v) {
selected = (valorDefault == v[campoValor]) ? ' selected="selected"' : '';
$option = $('<option value="' + v[campoValor] + selected + '">' + v[campoTextoXX] + "</option>");
$select.append($option);
});
return obj;
}
function crearSelect(trx, inputPar, outputPar, selectID, campoTextoXX, campoValor, valorDefault, callback) {
var request = getTrxData(trx, inputPar, outputPar);
request.done(function(data) {
var obj = {
datos: $.xml2json(data),
tipo: 'S',// Success
mensaje: "Datos obtenidos correctamente"
};
callback(makeOptions(obj, selectID, campoTextoXX, campoValor, valorDefault));
});
request.fail(function(jqXHR, textStatus, errorThrown) {
var obj = {
tipo: 'E',// Error
mensaje: "Error: " + textStatus
};
callback(obj);
});
}
crearSelect("Default/pruebas_frarv01/trxTest", {letra:'V'}, "*", 'selectID', "CustomerID", 'OrderID', '', function(retorno) {
alert(retorno.tipo + ": " + retorno.mensaje);
});
You will see that this is essentially a refactored version of your original code, with significant simplification of the string handling in getTrxData, which appears to work correctly.
The options code has been pulled out as a separate function, makeOptions, to make the new structure of crearSelect clearer. This is not strictly necessary and the code could be re-combined without penalty.
Tested here insomuch as to make sure it loads and runs through to the "Error" alert, which it does successfully. Without access to the server-side script, I can't test/debug the full ajax functionality so you may need to do some debugging.
The problem appears to be that you are overwriting the variable "pepe" somewhere in your code.
Also, check how you are assigning your callback function and parameter object. A quick look appears that it is not being supplied the correct parameters.
You should be careful not to use global variables within your success and error functions. so instead of:
success: function(data){
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
}
I think you should do something like:
success: function(data){
var retorno = {};
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
}
furthermore you should use Firebug for Firefox to step through your code and watch your variables to ensure that the data is coming in correctly, and not getting overwritten at any point
Your control flow is a bit confusing, and another thing you can do is check to make sure your callbacks and variables are correct using some typeof conditionals to make sure they are functions, etc. try doing things like this:
success: function(data){
var retorno = {};
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
if (typeof callback !== "function" || typeof data !== "object"){
console.log('error');
throw "callback or data is not correct type";
}
callback(retorno);
}
and make sure you aren't getting an error in the console.

Categories