get parameter of api callback - javascript

here is what i've got
var mods = this.registry.gmmods;
for (var i = 0; i < mods.length; i++) {
if(mods[i] != this.config.botid){
this.api.stalk(mods[i],true,function (data){
console.log(mods[i]);
});
}
}
only the console log outputs undefined and i can seem to figure out how to get that data in callback function as the callback data doesn't contain it
could anyone tell me how i might be able to do that

It's a problem with i in your closure, when callback of this.api.stalk is called chances are that i is mods.length. See the following example:
var i = 0;
var arr=["hi","there"];
for(i=0;i<arr.length;i++){
setTimeout(function(){
console.log(arr[i]); //undefined
console.log("and i is:"+i); //i will be 2
},100);
}
Here is how you can solve the closure problem:
var i = 0;
var arr=["hi","there"];
for(i=0;i<arr.length;i++){
setTimeout(
(function(index){
return function(){
console.log("Index is:"+index);//0 and 1
console.log("arr at index:"+arr[index]);//hi and there
console.log("i is:"+i);//2 and 2
console.log("arr at i:"+arr[i]);//undefined and undefined
}
})(i)
,100);
}
Your code could look something like:
var mods = this.registry.gmmods;
for (var i = 0; i < mods.length; i++) {
if(mods[i] != this.config.botid){
this.api.stalk(mods[i],true,
(function(index){
return function (data){
console.log("index is:"+index);
console.log(mods[index]);
console.log("i is:"+i);
console.log(mods[i]);
}
})(i)
);
}
}

Related

How To Add Delay To HTML Javascript Function

I have the following script that opens urls in a list:
function openWindow(){
var x = document.getElementById('a').value.split('\n');
for (var i = 0; i < x.length; i++)
if (x[i].indexOf('.') > 0)
if (x[i].indexOf('://') < 0)
window.open('http://'+x[i]);
else
window.open(x[i]);
}
However, I would like to add a delay (let's say about 5 seconds) between opening each url. How can I do this?
I'm not familiar with functions. Usually much better with Linux and such. Your insight is highly appreciated.
A better approach is to use setTimeout() along with a self-executing anonymous function:
function openWindow() {
var i = 0;
var x = document.getElementById('a').value.split('\n');
(function() {
if(typeof x[i] !== 'undefined') {
if(x[i].indexOf('.') > 0) {
if(x[i].indexOf('://') < 0) {
window.open('http://' + x[i++]);
} else {
window.open(x[i++]);
}
}
setTimeout(arguments.callee, 1000);
}
return false;
})();
}
This will guarantee that the next call is not made before your code was executed. I used arguments.callee in this example as a function reference. Once the index no longer exists in the array, by checking if it's undefined, it simply returns false instead of setting another timout.
You can do it like this, to avoid issues caused by setTimeout being non-blocking.
What you need is to wait for the setTimeout to be executed before starting the next iteration.
var i = 0;
function openWindow(){
var x = document.getElementById('a').value.split('\n');
doLoop(x);
}
function doLoop(x)
setTimeout(function () {
if (x[i].indexOf('.') > 0){
if (x[i].indexOf('://') < 0){
window.open('http://'+x[i]);
}else{
window.open(x[i]);
}
}
i+=1;
if(i<x.length){
doLoop(x);
}
}, 5000)
}
Using a self executing function, it'd go like this :
function openWindow() {
var i = 0;
var x = document.getElementById('a').value.split('\n');
(function fn() {
if(x[i].indexOf('.') > 0) {
if(x[i].indexOf('://') < 0) {
window.open('http://' + x[i++]);
} else {
window.open(x[i++]);
}
}
i++;
if( i < x.length ){
setTimeout( fn, 3000 );
}
})();
}
create array x with all url's
var x = [url1, url2, url3, ...];
create a for loop
for(var i = 0; i<x.length; i++) {
setTimeout(function() {
window.open('http://'+x[i])}, 1000); // 1000 for 1 second
}
}
setInterval(function(){window.open('http://'+x[i]);},5000);

callbacks when trying to create an array from asynchronous calls in javascript

I am trying to create an array from an asynchronous get request using a function that uses a for loop in order to pass a parameter in the get request.
var loadRarity = function () {
var rarities = [];
for (var i =0; i < deck.length; i++) {
Card.get({cardName: deck[i].card_name}, function(data) {
rarities.push(data.data[0].rarity);
console.log(rarities); //20 instances where the array is being populated
});
console.log(rarities);// result :20x [] empty array
}
return rarities;
};
var raritiesArray = loadRarity();
console.log(raritiesArray); //empty array
I can't figure out how to use the callback to make this work.
An option is to increment a counter to check if you are on the last callback an then do any needed operation in that last callback
var loadRarity = function () {
var rarities = [];
var counter = 0; // initialize counter
for (var i =0; i < deck.length; i++) {
Card.get({cardName: deck[i].card_name}, function(data) {
counter += 1; //increment counter
rarities.push(data.data[0].rarity);
console.log(rarities); //20 instances where the array is being populated
if(counter == deck.length){ //if true you are in the last callback
console.log(raritiesArray); // array with all the elements
}
});
}
return rarities;
};
var raritiesArray = loadRarity();
Waiting for all this async stuff to happen, your code that needs to use the result should be in its own callback, which runs when the result is available. For example:
var loadRarity = function(cb) {
var rarities = [],
counter = 0,
done = function(){
if(counter++ === deck.length - 1){
cb(rarities);
}
};
for (var i =0; i < deck.length; i++) {
Card.get({cardName: deck[i].card_name}, function(data) {
rarities.push(data.data[0].rarity);
done();
});
}
};
loadRarity(function(completedRarities){
console.log(completedRarities);
});
Sample (using an image onload fn to simulate your asysnc call): http://codepen.io/RwwL/pen/VeeEBR?editors=001

How to append two string or number for the function name in javascript

for(i=0;i< 6; i++ ){
function myFunc + 1() {
alert(i);
}
}
myFunc1();
This is my code I want to create function from myFunc1 to myFunc6, but it seems like it does not work, why??
for (var i = 0; i < 6; i++) {
window['myFunc' + i] = (function(i) {
alert(i);
})(i);
}
you can do like this :
var myFuncs = [];
for ( i=0; i<6; i++ ) {
(function(i){ myFuncs.push(function() { alert(i) }); })(i);
}
myFuncs[0]();

Using closures to capture onclick events

I'd like to correct this example:
var $foo = $('#foo');
for (var i = 0; i < 10; i++) {
$foo.append($('<li></li>').text(i).on('click', function() {
alert(i);
}));
}
so that it alerts the correct value of i when clicked.
How can I do this? I know that the answer is to use a closure, but I'm not sure how to implement it.
I've tried doing
$foo.append($('<li></li>').text(i).on('click', function() {
return (function(i) {
alert(i);
})();
}));
but that returns undefined.
JSFiddle here: http://jsfiddle.net/tmcw/4phm7/1/
The standard idea is to have an immediately invoked function :
var $foo = $('#foo');
for (var i = 0; i < 10; i++) {
(function(i){
$foo.append($('<li></li>').text(i).on('click', function() {
alert(i);
}));
})(i);
}
You need to create a copy of the i variable for each function:
$foo.append($('<li></li>').text(i).on('click', function(copy_i) {
return (function() {
alert(copy_i);
})(i);
}));

returning a value after for loops

So, I have been trying for the past few hours to get an result out of a function after performing some for loops :
Cluster.prototype.initiate_api_data_fetching = function(username) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function(data_object){
var json_obj = JSON.parse(data_object);
for(var obj_key in json_obj) {
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function(data_obj){
var json_object = JSON.parse(data_obj);
for(var data_key in json_object) {
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
};
};
log(object);
});
};
};
});
};
Making abstraction of all the variables and other things that make no sense to you readers, I would just like to know how can I return the object array with the data that I\m pushing in it. Everything is fine if I\m logging where the /*log(object);*/ is, but if I want to see what the object contains at the end of the function, I get an empty array.
I suggest you add a callback to your main function and call it when done..
Cluster.prototype.initiate_api_data_fetching = function (username, callback) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function (data_object) {
var json_obj = JSON.parse(data_object)
, counter = 0;
function done() {
counter -= 1;
if (counter === 0) {
callback(object);
}
}
for (var obj_key in json_obj) {
if (!json_obj.hasOwnProperty(obj_key)) { continue; }
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
counter += 1;
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function (data_obj) {
var json_object = JSON.parse(data_obj);
for (var data_key in json_object) {
if (!json_object.hasOwnProperty(data_key)) { continue; }
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
}
}
done();
});
}
}
});
};
PS. 1 assumption is that initiate_api_data_fetching is async.
PS. 2 Follow the advice from the commenters above to improve your code. I answered your immediate question by showing you how to synchronise async calls, but don't stop there.

Categories

Resources