从async false转到async true

时间:2012-12-31 02:38:29

标签: jquery ajax jquery-mobile

嗨所以我有一段代码运行了很多次

Loader.load方法( '数据/ map.json')

我的想法是,我可以传入任何json文件,加载器将处理它

所以这里是async false格式的加载器

  var Loader = {
    basePath: '',
    cache: {},
    load: function(name) {
        if(typeof this.cache[name] == 'undefined') {
            var loadUrl = (this.basePath == '') ? name : this.basePath + '/' + name;
            var parameters = {

                url: loadUrl,
                dataType: 'json',
                async: false,
                context: this,
                success: function(data) {
                    this.cache[name] = data;
                }
            };

            $.ajax(parameters);
        }
        return this.cache[name];
   }
};
return Loader;

但这是异步错误的格式,我需要将其转换为async true格式以便更好地使用jQuerymobile,所以在这里有一些帮助我设法让它达到了异步

的程度
var data = AsyncLoader.load('data/map.json').done(function(data, textStatus, jqXHR) {
            console.log("complete");

        }).fail(function(jqXHR, textStatus, errorThrown) {

            console.log("an error has occurred");

        }).always(function(jqXHR, textStatus) {
            console.log("running");
        });

这称为asynloader

function($) {
var AsyncLoader = {
    basePath: '',
    cache: {},
    load: function(name) {
        if(typeof this.cache[name] == 'undefined') {
            var loadUrl = (this.basePath == '') ? name : this.basePath + '/' + name;
            var parameters = {
                beforeSend: function() { $.mobile.showPageLoadingMsg(); },
                complete: function() {$.mobile.hidePageLoadingMsg(); },
                url: loadUrl,
                dataType: 'json',
                async: true,
                context: this,
                success: function(data) {
                    this.cache[name] = data;
                }
            };

            $.ajax(parameters);
        }

        return this.cache[name];
    }
};

return AsyncLoader;

问题是要使这个工作我需要返回$ .ajax(参数)而不是返回this.cache [name];否则我得到一个javascript错误..问题是,如果我更改它以获取$ .ajax(参数)当我第二次加载maps.json时它不会从this.cache获取数据它会加载json文件再次无用

任何人都可以提供帮助

谢谢:)

3 个答案:

答案 0 :(得分:1)

$.ajax返回a Deferred object。您也可以返回自己的Deferred对象。您的新代码可能看起来像这样:

load: function(name) {
    // Is the object already in the cache?
    if(Object.prototype.hasOwnProperty.call(this.cache, name)) {
        // Yes! Return a Deferred that's already been resolved.
        return jQuery.Deferred().resolve(this.cache[name]);
    }else{
        // No! We have to load it. Let's still use our own Deferred, though:
        var deferred = jQuery.Deferred();

        // There's our Deferred. Now let's load it.
        jQuery.ajax({
            // ...
        }).done(function(data) {
            // We loaded it successfully!
            // Add it to our cache and resolve the Deferred.
            this.cache[name] = data;
            deferred.resolve(data);
        }).fail(function() {
            // Fail! Pass the failure on to our deferred.
            deferred.reject.apply(deferred, arguments);
        });

        // We've started the AJAX request. Now return our Deferred.
        return deferred;
    }
}

答案 1 :(得分:0)

嗯,这不太合适..

如果我使用这个

收藏

var data = AsyncLoader.load('data/map.json').done(function(data) {

    var models = [];
    $.each(data.data.locations, function() {
        // RESERVED WORDS YO
        if(this['delete'] == 1) {
            return;
        }

        models.push(new MapLocationModel(this));

    });
    $t.reset(models);

});

async loader

function($) {
var AsyncLoader = {
    basePath: '',
    cache: {},
    load: function(name) {
        if(typeof this.cache[name] == 'undefined') {

            console.log("not cached");

            var deferred = jQuery.Deferred();
            var loadUrl = (this.basePath == '') ? name : this.basePath + '/' + name;
            var parameters = {
                beforeSend: function() { console.log("d"); },
                url: loadUrl,
                dataType: 'json',
                async: true,
                context: this,
                success: function(data) {
                    this.cache[name] = data;
                    deferred.resolve(data);
                }
            };

            $.ajax(parameters);
            return deferred;


        } else {

        console.log("cached");

        return jQuery.Deferred().resolve(this.cache[name]);

        }

    }
};

return AsyncLoader;

我会多次加载地图数据,永远不会从缓存中获取它。

但是如果我在上面改为async false它工作正常,但我需要异步才能成为现实

由于

答案 2 :(得分:0)

两个建议:

  • 避免this引用AsyncLoader

  • 使用Object.hasOwnProperty()而不是typeof .... == 'undefined'测试是否存在obhject属性。

JS:

function($) {
    var AsyncLoader = {
        basePath: '',
        cache: {},
        load: function(name) {
            var dfrd = $.Deferred();
            if(!AsyncLoader.cache.hasOwnProperty(name)) {
                var loadUrl = (AsyncLoader.basePath == '') ? name : AsyncLoader.basePath + '/' + name;
                $.ajax({
                    beforeSend: function() { console.log("d"); },
                    url: loadUrl,
                    dataType: 'json',
                    async: true,
                    success: function(data) {
                        AsyncLoader.cache[name] = data;
                        dfrd.resolve(data);
                    }
                });
            }
            else {
                return dfrd.resolve(AsyncLoader.cache[name]);
            }
            return dfrd.promise();
        }
    };
    return AsyncLoader;
...
}(jQuery);

备注

尽管AsyncLoader.load()可以在已经缓存数据时直接返回数据,但是当需要从服务器获取数据时,情况并非如此;原因是服务器响应是异步的。所需要的是一种机制,通过该机制,任何调用AsyncLoader.load()的表达式都可以以完全相同的方式接收数据,无论AsyncLoader.load()是从缓存还是从服务器获取数据。

所以在上面的代码中,AsyncLoader.load()不会尝试返回数据,至少不是传统意义上的;相反,它返回一个“promise”,如果所需数据已从缓存中获得,或者稍后在服务器响应时立即解析。

在这两种情况下,传递给dfrd.resolve(...)的值在调用AsyncLoader.load()的范围内变为可用,作为.done()(或.always()中指定的函数的参数或者.then())方法,在返回的promise上调用(通常通过方法链接)。

例如:

AsyncLoader.load('myName').done(function(data) {
    console.log(data);
    //do wheatever else is necessary with `data` here.
});

因此,实现了目标。通过返回一个promise(在AsyncLoader.load()内创建),所需的数据在AsyncLoader.load()范围之外以完全相同的方式可用,无论它是从缓存中提取还是从服务器刚刚接收到。

调用AsyncLoader.load()的表达式完全不知道数据是否来自缓存,但必须始终以正确的方式写入,以通过返回的promise接收数据。