Reputation: 69
I have following table in my database:
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| fullname | varchar(50) | YES | | NULL | |
| email | varchar(50) | YES | | NULL | |
| password | varchar(50) | YES | | NULL | |
| gender | varchar(50) | YES | | NULL | |
| birthdate | varchar(50) | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
I query the data from same via following ajax method:
function getUserDB(){
return ($.ajax({
url: 'services/users?',
method: 'get',
headers: { 'Accept': 'application/json' },
success: function(data) {
console.log ("getUserDB got the user data");
UserDB = JSON.stringify(data);
UserDBObj = JSON.parse(UserDB);
}
}));
}
I have an HTML page which should display the fullname
at various places (divs) depending on the id
.
In order to avoid firing the jQuery for each div
, I thought I can store the response on page load and use another method to get the fullname
.
Here is what I wrote:
function getUserName(ID){
var username;
console.log(" getUserName called");
for(var index in UserDBObj){
if (UserDBObj[index] == ID)
{
username = UserDBObj[index].fullname;
console.log("Got username : "+ username);
}
}
return username;
}
I call getUserName(id)
for the respective div where the name has to be shown.
However this is not working because the ajax call is asynchronous and getUserName(id)
is getting called even before the data is acquired.
Any suggestion how to achieve this? I have seen similar questions but none of them appeared conclusive.
Upvotes: 1
Views: 473
Reputation: 12728
What you basically can do (not changing the general behavior of your application), is make the getUserName function also asynchronous, since it is depending on a asynchronous event.
One possibility to to that, could look this way:
(I give only an outline, not the complete code)
function setUsername(ID, divId) {
if (UserDBObj_isLoaded) {
// do as before
}
else {
// set callback function that will be called from the
// ajax-call success handler
var cb = function() {
// get the value for the name
...
// set the name into the divId
...
}
UserObj_cbs.push(cb);
}
}
Here an outline of the success handler only:
success: function(data) {
console.log ("getUserDB got the user data");
UserDB = JSON.stringify(data);
UserDBObj = JSON.parse(UserDB);
UserDBObj_isLoaded = true;
// process all the callback functions till now
for (i=0; i<UserDBObj_cbs.length; i++) {
UserDbObj_cbs[i]();
}
}
Upvotes: 0
Reputation: 430
try calling the function after ajax call is completed
$.ajax({
url: 'services/users?',
method: 'get',
headers: { 'Accept': 'application/json' },
success: function(data) {
console.log ("getUserDB got the user data");
UserDB = JSON.stringify(data);
UserDBObj = JSON.parse(UserDB);
}
}),getUserName());
Upvotes: 1
Reputation: 5929
Promises (Deferred objects in jQuery environments) are the nicest way of dealing with requirements like this. It lets you deal with your async calls in a manner which lets you ignore the specific timing of your xhr calls. In the code below, your ajax call only gets called once, and from then on, whenever you call the getUser
function, it just uses the cached results of the xhr call without repeating it. There is no need for you to track 'if ajax results are loaded' or anything like that.... the promise does that for you.
MDN on ES6 Promises spec: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
jQuery Deferred spec (same idea as Promises): https://api.jquery.com/category/deferred-object/
var xhrUsers = $.get('/api/users');
function getUser(id) {
return xhrUsers.then(function(usersList) {
return usersList[id];
});
}
function getUserFullName(id) {
return xhrUsers.then(function(usersList) {
return usersList[id].fullname;
});
}
//example
getUser('bob').done(function(user) {
//do something with user bob
});
getUserFullName('jane').done(function(fullname) {
console.log('user jane\'s full name is: ' + fullname);
});
Upvotes: 1
Reputation: 435
Execute your data handling routine once it has been loaded.
Something like this (you will have to replace 'myDivSelector'):
function populateUsers() {
$(myDivSelector).each(function () {
var name = getUserName(this.id);
//handle user name
});
}
function getUserDB(){
return ($.ajax({
url: 'services/users?',
method: 'get',
headers: { 'Accept': 'application/json' },
success: function(data) {
console.log ("getUserDB got the user data");
UserDB = JSON.stringify(data);
UserDBObj = JSON.parse(UserDB);
populateUsers();
}
}));
}
Upvotes: 0