我的数据库中有以下表:
+-----------+-------------+------+-----+---------+----------------+
| 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 | |
+-----------+-------------+------+-----+---------+----------------+
我通过以下ajax方法查询相同的数据:
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);
}
}));
}
我有一个HTML页面,应该根据id
在不同的地方(div)显示fullname
。为了避免为每个div
触发jQuery,我认为我可以在页面加载时存储响应,并使用另一种方法来获取fullname
。以下是我写的:
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;
}
对于必须显示名称的相应div,我调用getUserName(id)
。然而,这是不工作的,因为ajax调用是异步的,getUserName(id)
甚至在获取数据之前就被调用了。
有什么建议吗?我看到过类似的问题,但没有一个是决定性的。
Promises (jQuery环境中的延迟对象)是处理此类需求的最佳方式。它允许您以一种可以忽略xhr调用的特定时间的方式处理异步调用。在下面的代码中,ajax调用只被调用一次,从那时起,无论何时调用getUser
函数,它都只使用xhr调用的缓存结果,而不重复它。没有必要为您跟踪'如果ajax结果加载'或类似的....承诺会帮你做到这一点。
MDN on ES6 Promises规范:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
jQuery Deferred规范(和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);
});
尝试在ajax调用完成后调用函数
$.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());
加载后执行数据处理例程。
像这样的东西(你将不得不替换'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();
}
}));
}
您基本上可以做的(不改变应用程序的一般行为)是使getUserName函数也是异步的,因为它依赖于异步事件。
一种可能是这样的:
(我只给出一个大纲,没有给出完整的代码)
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);
}
}
下面是成功处理程序的概要:
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]();
}
}