如何等待另一个回调的ajax回调结果?

时间:2012-11-16 11:26:18

标签: javascript jquery

我有一个方法如下:

 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请求。

我该如何解决这个问题? (请求必须是异步的)

4 个答案:

答案 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成功函数中添加一个回调函数,该函数将最终结果传递给另一个函数,该函数处理其余的执行。