Ajax done call how to pass a variable by copy - javascript

Here is my code :
for (var i = 0; i < list.length; i++) {
$.when(
$.ajax({url: "./dorequest.php?id=" + list[i],
success: function(response){ jsonFriendlist = response; }}) ).done(
function(jsonFriendlist) {
var friendListObject = JSON.parse(jsonFriendlist);
if (!jQuery.isEmptyObject(friendListObject)) {
var rawListFriend = friendListObject.friendslist.friends;
for (var j = 0; j < rawListFriend.length; j++) {
console.log(i);
playerLinkList[i].listFriends.push(rawListFriend[j].id);
}
}
}
);
}
Basicly I try to update a part of an object in the array list sending a request by item i that array. But the code fail because every call to the "done" function i done with i = 13 (which is list.lenght).
My understanding is that since the request take time to be send an retrieve the result and since it's done async when the done function is call the main thread is already out of the forso i = 13.
My question is how can I manage to "freeze" i by passing it by copy when the ajax request is sent ?
Thanks,

Using a closure solved the issue.
for (var i = 0; i < playerIds.length; i++) {
// Pass the parameter "i" to the done functions
(function(index) {
var dfd = $.ajax({url: "./dorequest.php?id=" + playerIds[i] + "&requesttype=friendlist",
success: function(response){ jsonFriendlist = response; }});
dfd.done(
function(jsonFriendlist) {
var friendListObject = JSON.parse(jsonFriendlist);
if (!jQuery.isEmptyObject(friendListObject)) {
var rawListFriend = friendListObject.friendslist.friends;
for (var j = 0; j < rawListFriend.length; j++) {
playerLinkList[index].listFriends.push(rawListFriend[j].steamid);
}
}
}
);
})(i);
}

Related

How to get outside data in promise.then callback function

Now I want to bind the data responded with function "getPresentationFilterValues" with filterItem.
How can I get the data of filter Item when calling the callback function with promise? Following is the code.
$q.all(presentationPromiseList).then(
function(response){
for(var i=0; i<response.length; i++){
config = self.bindAppPresentation(response[i], {config:config});
var filtering = config.configuration.filtering;
for(var i = 0; i< filtering.length; i++){
for(var j = 0; j < filtering[i].filters.length; j++){
var filterItem = filtering[i].filters[j];
if(filterItem.source == 'dynamic'&& !filterItem.options){
responsePromise = reveal.getPresentationFilterValues(filterItem);
responsePromise.then(function(response){
}).catch(function(ex){});
}
}
}
}
console.log("App presentation bind");
return 'param1';
},
function(response){
return $q.reject(new Error("failed to get app presentation: " + response.data.message));
}
)
Something like this:
const outsideData = 1
someFunctionWhichReturnsPromise().then(function() { return outsideData })

How to make $.post requests run in order with using ajax alternative

Is it possible to execute $.post requests synchronously? I have the following code:
function loadTest() {
var questionIDs = [];
var count = 0;
console.log("getting test");
$.post("db.php", function(data) {
obj = jQuery.parseJSON(data);
var questionCount = obj.length;
console.log(obj);
while (count != questionCount) {
questionIDs.push(obj[count].id);
count++;
}
console.log(questionIDs);
// $('#question').html(obj[0].question);
});
$.post("getChoices.php", {
IDs: questionIDs
}, function(data) {
console.log(data);
obj = jQuery.parseJSON(data);
console.log(obj);
while (q < 3) {
console.log("question");
var w = 1;
while (w < 5) {
console.log(obj[q][w]);
w++;
}
q++;
}
// $('#question').html(obj[0].question);
});
}
Due to the $.post functions running asycnchronously, the variable questionIDs will be empty when being sent. Is there a possible solution for this that doesn't require changing from $.post to ajax? I've tried various solutions on here but I can't seem to get them to work.
Make sure you make the second request once the first one has been responded. Put the second request inside the first request callback. Like this:
function loadTest() {
var questionIDs = [];
var count = 0;
console.log("getting test");
$.post("db.php", function(data) {
obj = jQuery.parseJSON(data);
var questionCount = obj.length;
console.log(obj);
while (count != questionCount) {
questionIDs.push(obj[count].id);
count++;
}
console.log(questionIDs);
// $('#question').html(obj[0].question);
$.post("getChoices.php", {
IDs: questionIDs
}, function(data) {
console.log(data);
obj = jQuery.parseJSON(data);
console.log(obj);
while (q < 3) {
console.log("question");
var w = 1;
while (w < 5) {
console.log(obj[q][w]);
w++;
}
q++;
}
// $('#question').html(obj[0].question);
});
});
}

Execute multiple functions

I have an Object, InsertDB, that contains multiple functions. I would like to execute one after the other.
Only execute function 2 InsertDB.addNot(); when function 1 InsertDB.addBk(); has completely finished looping, inserting records, and so on.
// Object with 7 functions to be called. Each performs a loop and insert records into IndexedDB
InsertDB = {
addBk: function(Object) {
if (Object.hasOwnProperty("Books")) {
for (var i = 0, j = Object["Books"].length; i < j; i++) {
server.Books.add({
title: Object["Books"][i].id,
content: Object["Books"][i]
});
}
}
},
addNot: function(Object) {
if (Object.hasOwnProperty("Notifications")) {
for (var i = 0, j = Object["Notifications"].length; i < j; i++) {
server.Notifications.add({
content: Object["Notifications"][i]
});
}
}
} etc...
}
//On Ajax success event, run above functions one after the other as described above.
Synchronize = {
Start: function(){
return $.ajax({
......
success: function(data){
var Object = $.parseJSON(data);
InsertDB.addBk(Object);
InsertDB.addNot(Object);
InsertDB.addUser(Object);
InsertDB.addHistory(Object); ect...
}
}};
Synchornize.Start();
You should implement the functions so that they return promises, and then you can subscribe to those promises. You can use jQuery or q.js for that.
As Tommi suggeted, I had to ensure that the function returns promises then I can fire an event when all iterations are finished, I did do as follow :
InsertDB = {
addBk: function(Object) {
if (Object.hasOwnProperty("Books")) {
var promises = [],p;
for (var i = 0, j = Object["Books"].length; i < j; i++) {
p = server.Books.add({
title: Object["Books"][i].id,
content: Object["Books"][i]
});
promises.push(p);
}
$.when.apply($, promises).done(function() {
// callback function when all iterations are finished
});
}
}

Nodejs calling function from within a function

I have 3 methods
exports.getImageById = function (resultFn, id) {
...
}
exports.getCollectionById = function (resultFn, id) {
}
in the third method I want to call both methods
exports.getCollectionImages = function (resultFn, collectionId) {
var arr = new Array();
this.getCollectionById( // fine, 1st call
function (result) {
var images = result.image;
for (i = 0; i < images.length; i++) {
this.getImageById(function (result1) { // error, 2nd call
arr[i] = result1;
}, images[i]
);
}
}
, collectionId
);
resultFn(arr);
}
I can call first function this.getCollectionById but it fails to call this.getImageById, it says undefined function, whats the reason for that?
When you call this.getCollectionById passing it a callback, the callback doesn't have access to the same this
The simplest solution is to save this as a local variable.
exports.getCollectionImages = function (resultFn, collectionId) {
var arr = new Array();
var me = this; // Save this
this.getCollectionById( // fine, 1st call
function (result) {
var images = result.image;
for (var i = 0; i < images.length; i++) {
// Use me instead of this
me.getImageById(function (result1) { // error, 2nd call
arr[i] = result1;
}, images[i]);
}
}, collectionId);
resultFn(arr);
}
The value of this inside the inner function is not the same object as outside, because it's determined depending on how the function is called. You can find a detailed explanation in the MDN article on this.
One of the ways to solve it is by keeping a reference to the outer this in another variable such as that:
var that = this;
this.getCollectionById( // fine, 1st call
function (result) {
var images = result.image;
for (i = 0; i < images.length; i++) {
that.getImageById(function (result1) { // 2nd call
arr[i] = result1;
}, images[i]
);
}
}
, collectionId
);

How can I pass a variable parameter to an anonymous function using jquery?

Can someone tell me what I am doing wrong here? I simplified it below but I am basically trying to create a list and have a click event that references a variable only available in the loop.
for (var i = 0; i < data.length; i++) {
$newRow = $(rowFormat);
$('a:first', $newRow).click(function(i){
return function() { alert(i); }
});
$list.append($newRow);
}
You aren't calling the outer function.
$('a:first', $newRow).click(function(j){
return function() { alert(j); }
}(i)); /* Pay special attention to this line, it is where the major change is */
As T.J. Crowder mentioned, you can move the factory out of the loop.
function my_factory(j) {
return function() {
alert(j);
};
}
$('a:first', $newRow).click(my_factory(i));
You've almost got it, just one small change. This is actually my favorite example of a practical use of a closure in Javascript.
Basically, you need to create a function that takes a value, and returns a function that uses that value. See the commented line below for what your example is missing. Your code created the anonymous function, but didn't invoke it.
for (var i = 0; i < data.length; i++) {
$newRow = $(rowFormat);
var fn = (function (value) {
return function() {
alert(value);
};
}) (i); //this is what you were missing, you need to invoke the anonymous function
$('a:first', $newRow).click(fn);
$list.append($newRow);
}
Use 'bind' to attach the 'click' event and pass a parameter. Using 'event.data' you will be able to get the right value of your parameter:
Example 1:
$(document).ready(function()
{
for (var i = 0; i < data.length; i++)
{
$newRow = $(rowFormat);
$('a:first', $newRow).bind('click', {i: i},
function (event)
{
alert(event.data.i);
}
);
$list.append($newRow);
}
});
Example 2:
$(document).ready(function()
{
$(".selectorA").each(function()
{
var elementId = $(this).attr("id");
for(var i = 0; i < 20; i++)
{
$('#question' + i).bind('click', {currentIndex: i, elementId: elementId},
function (event)
{
alert(event.data.currentIndex + " | " + event.data.elementId);
}
);
}
}
});

Categories