我有一个方法如下:
self.getOrAddCache = function (key, objectFactory) {
var data = self.getFromCache(key);
if (!data) {
data = objectFactory();
if (data && data != null)
self.addToCache(key, data);
}
return data;
};
我这样用:
function getCities()
{
var cities = getOrAddCache(CacheKeys.Cities, function() {
var cityArray = new Array();
// get city informations from service
$.ajax({
type: "GET",
async: true,
url: "service/cities",
success: function (response) {
$.each(response, function(index, value) {
cityArray.push({
name: value.name,
id: value.id
});
});
}
});
if (cityArray.length > 0)
return cityArray;
else {
return null;
}
});
return cities;
}
getCities
函数始终返回null
,因为getCities
没有等待完成异步ajax请求。
我该如何解决这个问题? (请求必须是异步的)
答案 0 :(得分:3)
最好的解决方案是使用Deferred对象。由于您需要将AJAX调用设置为异步,因此您应该让getCities
函数返回 promise 以在将来的某个时间点返回该数据。
您可以存储这些承诺,而不是将原始数据存储在缓存中。
如果您请求已经解决的承诺,则会立即完成。如果已经存在对缓存对象的挂起请求,则将启动异步AJAX调用,并且将按顺序启动等待该promise的所有未完成回调。
像这样的东西应该工作,虽然这当然是未经测试的,E& OE等等。
self.getCached = function(key, objectFactory) {
var def = self.getCache(key);
if (!def) {
def = objectFactory.call(self);
self.addToCache(key, def);
}
return def;
}
function getCities() {
return getCached(CacheKeys.Cities, function() {
return $.ajax({
type: 'GET',
url: 'service/cities'
}).pipe(function(response) {
return $.map(response, function(value) {
return { name: value.name, id: value.id };
});
});
});
}
请注意使用.pipe
将AJAX响应后处理为所需格式,结果是另一个延迟对象,实际上后者存储在缓存中。
现在的用法是:
getCities().done(function(cities) {
// use the cities array
});
答案 1 :(得分:1)
回调:
function getCities(callbackFunction)
{
var cities = getOrAddCache(CacheKeys.Cities, function() {
var cityArray = new Array();
// get city informations from service
$.ajax({
type: "GET",
async: true,
url: "service/cities",
success: function (response) {
$.each(response, function(index, value) {
cityArray.push({
name: value.name,
id: value.id
});
});
callbackFunction(cityArray);
}
});
});
}
getCities(function(cityArray){
// do stuff
});
答案 2 :(得分:1)
您无法从异步提取数据的函数返回结果。
将您的getCities功能更改为接受回调的功能:
function fetchCities(callback) {
var cities = getOrAddCache(CacheKeys.Cities, function() {
var cityArray = new Array();
// get city informations from service
$.ajax({
type: "GET",
async: true,
url: "service/cities",
success: function (response) {
$.each(response, function(index, value) {
cityArray.push({
name: value.name,
id: value.id
});
});
if (callback) callback(cityArray);
}
});
});
}
并像这样使用它:
fetchCities(function(cities) {
// use the cities array
});
请注意,在技术上可以使用async:true
使代码等待响应但不使用它:这是一种糟糕的做法,它会锁定页面直到服务器应答。
答案 3 :(得分:0)
你似乎在与自己发生矛盾。
根据定义,异步的东西不会暂停脚本以等待它的执行结束。如果确实等待,则不能异步。
解决此问题的最佳方法是在ajax成功函数中添加一个回调函数,该函数将最终结果传递给另一个函数,该函数处理其余的执行。