Fill array through ajax request - javascript

I need to gather some data from the database through AJAX and place it in an array. Unfortunatly I'm unable to archieve this for some reason.
AJAX sends data to retrieve specific data. This data is as follows:
[{"comment_id":154,"comment_text":"Moduleboeken PHP","date_updated":"2015-06-01 10:34:47"},{"comment_id":155,"comment_text":"Moduleboeken JAVA","date_updated":"2015-06-01 10:34:54"}]
[{"comment_id":149,"comment_text":"Werksfeer","date_updated":"2015-06-01 10:33:57"}]
[{"comment_id":152,"comment_text":"Begeleiding Elleke Jagersma","date_updated":"2015-06-01 10:34:27"}]
[{"comment_id":260,"comment_text":"Studievoortgang JAVA","date_updated":"2015-06-01 13:01:15"}]
[{"comment_id":153,"comment_text":"Faciliteiten","date_updated":"2015-06-01 10:34:39"}]
The function to gather this data:
function sendRetrieveAjax(url, data) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url, type: 'post', data: data,
success: function(data) {
resolve(data);
},
error: function(request, status, error) {
reject([{request: request, status: status, error: error}]);
}
});
});
}
Main code runs through 5 DOM elements, gathers an ID from them and uses this in the AJAX send and retrieve function. If this is succesfull it places it in an array.
var elements = $('.note_block');
var dataCollection = new Array();
for(i = 0; i < elements.length; i++) {
var element = $(elements[i]);
var data = {
commenttype_id : element.children('#commenttype_id').val(),
week_id : $('#week_id').val()
}
sendRetrieveAjax('../functions/getcomments.php', data).then(function(data) {
console.log(data);
dataCollection[i] = data;
});
}
console.log(dataCollection);
The array unfortunatly is empty, while the console shows the correct data.
Can someone enlighten me?

You have two problems
You need to bound the value of i to the sendRetrieveAjax
You need to print the value of dataCollection after filling it (note the use of promise)
To solve the first problem you need to use IIFE (Immediately-Invoked Function Expression)
for(i = 0; i < elements.length; i++) {
var element = $(elements[i]);
var data = {
commenttype_id : element.children('#commenttype_id').val(),
week_id : $('#week_id').val()
}
(function(_i) {
sendRetrieveAjax('../functions/getcomments.php', data).then(function(data) {
console.log(data);
dataCollection[_i] = data;
});
})(i);
}
And to solve the second problem, you can use an array or promises to keep all request's promises in it, and execute them either sequential or parallel
var requests = []
;
for(i = 0; i < elements.length; i++) {
var element = $(elements[i]);
var data = {
commenttype_id : element.children('#commenttype_id').val(),
week_id : $('#week_id').val()
}
// No need to store the URL, just store the data
requests.push(data);
}
requests = requests.map(function(data) {
return sendRetrieveAjax('../functions/getcomments.php', data);
});
Promise.all(requests).done(function(responses) {
console.log(responses);
dataCollection = responses;
}, function(err) {
});

You need to map each individual response to correct array index. The most optimal solution in this case would be to use $.when to provide an array of promises and the get centralized response object with ordered response data objects.
I also simplified sendRetrieveAjax as $.ajax already returns promise object:
function sendRetrieveAjax(url, data) {
return $.ajax({
url: url,
type: 'post',
data: data
});
}
var promises = $('.note_block').map(function(i) {
return sendRetrieveAjax('../functions/getcomments.php', {
commenttype_id: $(this).children('.commenttype_id').val(),
week_id: $('#week_id').val()
});
}).get();
$.when.apply(null, promises).then(function() {
var dataCollection = $.map(arguments, function(data) {
return data[0];
});
console.log('Data Collection', dataCollection);
});
Another thing, don't duplicated ids, use .commenttype_id classes instead.
Here is a demo: http://plnkr.co/edit/r9NnlxIQjUhNvTYwfLy7?p=preview

Related

Storing ajax response data into array and compare it to the last values

I am stuck with these. I want to create a function to be run every 4secs. Now My function will get all the queue_id from my database and store it in array again and again, after storing it, i will compare it again and again every 4 secs, if there are changes , then i will do something.
Example execution : If my database response with queue_id's: 1,2,3,4,5 then i will store these data from an array. After storing it, i will query again evry 4 seconds if it returns 1,2,4,5 or 1,2,3,5 i will do something, but if it returns thesame like 1,2,3,4,5 then i will not do something.
I have no idea how to store or create array in javascript . Please help me:
function check_getqueue(clinicID, userID) {
$.ajax({
url: siteurl+"sec_myclinic/checkingUpdates/"+clinicID+"/"+userID,
type: "POST",
dataType: "JSON",
success: function(data) {
for(var i=0;i<data.length;i++) {
var tmpCountQ = data[i]['queue_id'];
};
if (tmpCountQ < lastcountQueue) {
}
lastcountQueue = tmpCountQ;
}
});
}
You need to keep track of the lastly received set of ids and compare them with the new ones. When a difference found, call your doSomething() and update the record for next run.
To get things faster you can first check the lengths. More info in the comment blocks below.
var previousQueueIDs = [];
function doSomething() {
// do something
// ...
// set timer for the next run
setTimeout(check_getqueue, 4000);
}
function check_getqueue(clinicID, userID) {
$.ajax({
url: siteurl+"sec_myclinic/checkingUpdates/"+clinicID+"/"+userID,
type: "POST",
dataType: "JSON",
success: function(data) {
var queueIDs = [];
if(previousQueueIDs.length != data.length) {
previousQueueIDs = queueIDs;
return doSomething();
}
// length didn't change, so check further
// create new array for the current values
for(var i=0;i<data.length;i++) {
queueIDs.push(+data[i]['queue_id']);
};
// sort them for faster comparison
queueIDs.sort( function(a,b) {
return a-b;
});
// check one by one and exit to run doSomething
// as soon as the first difference found
for(var i=0; i<queueIDs.length; i++) {
if(queueIDs[i] != previousQueueIDs[i]) {
previousQueueIDs = queueIDs;
return doSOmething();
}
}
// no difference this time, just set timer for the next run
setTimeout(check_getqueue, 4000);
}
});
}
Use push, and declare the array outside the ajax request. now all working
function check_getqueue(clinicID, userID) {
var tmpCountQ = [];
var lastCon = [];
$.ajax({
url: siteurl+"sec_myclinic/checkingUpdates/"+clinicID+"/"+userID,
type: "POST",
dataType: "JSON",
success: function(data) {
for(var i=0;i<data.length;i++) {
tmpCountQ.push(data[i]['queue_id']);
};
if(typeof lastCon[0] != "undefined")
{
for(j=0;j < tmpCountQ.length;j++)
{
if(tmpCountQ[j] != lastCon[j])
{
lastCon[j] = tmpCountQ[j];
}
}
}
else
{
lastCon = tmpCountQ;
}
console.log(tmpCountQ);
}
});
}

Fill array by multiple AJAX requests, then pass array to another function

(My solution below)
I have several HTML elements with class .canvas-background of which information is stored in the database. I want to get the information of each element and process it via JavaScript. But somehow I can't pass the response of the AJAX request to another function. Here is what I've tried:
function initTabs() {
var tabs = loadTabInformation();
console.log(tabs); // (1)
// do something else
}
function loadTabInformation() {
var requests = new Array();
var tabs = new Object();
var counter = 0;
$(".canvas-background").each(function () {
var tabNumber = $(this).data("tab-number");
var request = $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(tabNumber),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
})
.done(function (response) {
tabs[counter++] = response;
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log("request error in loadTabInformation()");
console.log(textStatus);
console.log(errorThrown);
});
requests.push(request);
});
$.when.apply($, requests).done(function () {
console.log(tabs); // (2)
return tabs;
});
}
At (1) I get undefined, but at (2) everything seems to be alright.
THE SOLUTION:
Thanks to the answer and the link in the comment #Kim Hoang provided I got this working. The clue seemed to put the done() function in the calling function, that is initTabs() in my case. Another thing I got wrong was to try to do the logic that should be executed after the AJAX requests had finished outside the done callback function. They must be inside (makes sense, if you think about it). And a lot of conosle output helped, to see what function returns what kind of object.
function initTabs() {
var tabInfoRequest = loadTabInfo();
tabInfoRequest[0].done(function() {
var results = (tabInfoRequest[1].length > 1) ? $.map(arguments, function(a) { return a[0]; }) : [arguments[0]];
for (var i = 0; i < results.length; i++) {
// do something with results[i]
}
});
}
function loadTabInfo() {
var tabNumbers = new Array();
$(".canvas-background").each(function () {
tabNumbers.push($(this).data("tab-number"));
});
var requests = $.map(tabNumbers, function (current) {
return $.ajax({
type: 'POST',
url: '../db/GetTabInformation.ashx',
data: String(current),
dataType: 'json',
contentType: 'text/plain; charset-utf-8'
});
});
var resultObject = new Object();
resultObject[0] = $.when.apply($, requests);
resultObject[1] = requests;
return resultObject;
}
Note: I only did the resultObject-thing because I needed the array requests in the initTabs() function.
Thank you very much for helping me!
You do not return anything in loadTabInformation, so of course you will get undefined. You should do it like this:
function loadTabInformation() {
...
return $.when.apply($, requests);
}
function initTabs() {
loadTabInformation().done(function (tabs) {
console.log(tabs); // (1)
// do something else
});
}

Parse Promises Multiple httpRequest Cloud Code

I'm writing an iOs app with Parse.com and Cloud Code. Actually I want to retrieve objects which contain one picture and other informations from a website and I want to add them to a class named News. When I run my code, every object is saved (in my class, one row = one retrieved object) but unfortunately the only first one has its picture saved.... Any idea ?
I made a lot of searches about promises (series / parallels) and I think the problem comes from here..
Note : don't worry about myLink, myImgLink : I put this to make my code easy to read !
Parse.Cloud.define("rajouteNews", function(request, response) {
Parse.Cloud.httpRequest({ url: 'myUrl'}).then(function(httpResponse) {
var news = [];
var NewsClass = Parse.Object.extend("news");
for (var i = 0; i < 10 ; ++i) {
var maNews = new NewsClass();
maNews.set("link", myLink[i]); // "Other informations"
maNews.set("imgLink", myImgLink[i]);
maNews.set("title", myTitle[i]);
var promises = [];
promises.push(Parse.Cloud.httpRequest({
url: $('img').attr('src'),
method: 'GET',
}).then(function(httpResponse){
var imgFile = new Parse.File("photo.jpg", {base64:httpResponse.buffer.toString('base64')});
maNews.set("image",imgFile); // The picture
return maNews.save();
}));
news.push(maNews);
}
promises.push(Parse.Object.saveAll(news, {
success: function (list) {
response.success(news.length.toString() + " ont été sauvegardées");
},
error: function (list, err) {
response.error("Error adding news");
}
}));
return Parse.Promise.when(promises);
}).then(function(bla,result){
response.success("Job done");
}, function(error) {
response.error(error);
}
);
});
Your promises array should put out of the for loop scope. Otherwise , your promise array would be assigned to be a new blank array each loop.
Parse.File would be saved automaticly when its parent do save, you don't need to save it in advance.
So I improve your code as following, try it and tell me weather it works.
Parse.Cloud.define("rajouteNews", function(request, response) {
Parse.Cloud.httpRequest({
url: 'myUrl'
}).then(function(httpResponse) {
var promises = [];
var NewsClass = Parse.Object.extend("news");
for (var i = 0; i < 10; ++i) {
var maNews = new NewsClass();
maNews.set("link", myLink[i]); // "Other informations"
maNews.set("imgLink", myImgLink[i]);
maNews.set("title", myTitle[i]);
var maNewsPromise = Parse.Cloud.httpRequest({
url: $('img').attr('src'),
method: 'GET',
}).then(function(httpResponse) {
var imgFile = new Parse.File("photo.jpg", {
base64: httpResponse.buffer.toString('base64')
});
maNews.set("image", imgFile); // The picture
return maNews.save();
});
promises.push(maNewsPromise);
}
return Parse.Promise.when(promises)
}).then(function(bla, result) {
// this function is call when `Parse.Promise.when(promises)` is done,
//I can't figure out why you take two params.
response.success("Job done");
}, function(error) {
response.error(error);
});
});

How can I list my twitter followers list in WinJS.UI.ListView

I want to list all my twitter followers in my WinJS.UI.ListView.
WinJS.xhr({
url: "https://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=" + twitterusername,
responseType: "json"
}).then(
function (xhr) {
var json = JSON.parse(xhr.responseText);
var a = [];
a = json.ids;
//
// now what next?
//
},
function (error) {
myListView.textContent = error;
}
);
I get all my twitter follores id by json.ids.
But next how to find their screen names and prifile pictures and main thing how to bind them with my ListView control. Becouse I had bind simple my static data into ListView but for this example i have no idea.
You have to make another call for each ids to api.twitter.com/1/users/show.json?user_id=json.ids[i].
After you receive all callbacks, you have to create an array with objects that have title, text and picture properties. After that simply bind it with you list.
The following code is an exemple (not tested, don't know if it's functional, but it should point you in the right direction)
var followersCallback = function(xhr){
var json = JSON.parse(xhr.responseText);
var promises = [];
// make promises for each user id (call to twitter to get picture/name/description)
for (var i = 0; i < json.ids.length; i++){
var promise = WinJS.xhr({
url: "https://api.twitter.com/1/users/show.json?user_id=" + json.ids[i],
responseType: "json"
});
promises.push(promise);
}
var dataArray = [];
// join those promises
WinJs.Promise.join(promises)
.then(function(args){
//when you get callback from all those promises
for (var j = 0; j < args.length; j++){
//not sure if parse is needed
args[j]=JSON.parse(args[j].responseText);
//populate your data array
var obj = {};
obj.title = args[j].name;
obj.picture = args[j].profile_image_url;
obj.text = args[j].description;
dataArray.push(obj);
}
//bind your data to the list
var dataList = new WinJS.Binding.List(dataArray);
});
};
WinJS.xhr({
url: "https://api.twitter.com/1/followers/ids.json?cursor=-1&screen_name=" + twitterusername,
responseType: "json"
}).then(
followersCallback,
function (error) {
myListView.textContent = error;
}
);

Javascript assign functions returned array to another array with all elements

In $(document).ready I am making in ajax request in a function, which returns json data which I add to an array. I am returning the array from that function but when I try to assign whats returned to another array my alert doesn't show an array full of values.
function retrieveGroupNames() {
var rows = new Array();
$.ajax({
type: "POST",
url: '#Url.Action("LookUpGroupName", "UserManager")',
dataType: "json",
data: {},
success: function (data) {
for (var i = 0; i < data.length; i++) {
rows[i] = {
data: data[i],
value: data[i].group,
result: data[i].group
}
// alert(data[i].group);
// alert(data[1].group);
} // end of for loop
// alert(rows[1].value);
} // end of success
}); // end of ajax
// alert(rows); data here
return rows;
} // end of function
$(document).ready(function () {
chkSelection();
var rows = [];
rows = retrieveGroupNames();
alert(rows);
});
Some help please? Thanks!
AJAX is asynchronous. You can't return stuff that relies on the request being finished. You need to use a callback instead:
function retrieveGroupNames(callback) {
$.ajax({
type: "POST",
url: '#Url.Action("LookUpGroupName", "UserManager")',
dataType: "json",
data: {},
success: function(data) {
var rows = [];
for(var i = 0; i < data.length; i++) {
rows[i] = {
data: data[i],
value: data[i].group,
result: data[i].group
}
}
callback(rows);
}
});
}
$(document).ready(function() {
chkSelection();
retrieveGroupNames(function(rows) {
alert(rows);
});
});
The other option other than the callback provided in ThiefMaster's answer is to use $.Deferred objects. Using deferreds gives you control over when and what should happen during asynchronous processing, such as ajax calls.
function retrieveGroupNames() {
// create a deferred object
var deferred = new $.Deferred();
$.ajax({
...
success: function(data) {
var rows = [];
for(var i = 0; i < data.length; i++) {
rows[i] = {
data: data[i],
value: data[i].group,
result: data[i].group
}
}
// resolve the deferred and pass the rows as data
deferred.resolve(rows);
}
});
// return a promise
return deferred.promise();
}
$(document).ready(function () {
// use the when...then syntax to consume the deferred function
$.when(retrieveGroupNames()).then(function (rows) {
// do whatever you want with rows
});
});
Also note that $.ajax already returns a promise itself, so you could just say return $.ajax({...}); in your retrieveGroupNames function.

Categories

Resources