1

嗨,我有一段代码运行了好几次

Loader.load('data/map.json')

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

所以这是异步错误格式的加载器

  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;

但这是异步错误格式,我需要将其设置为异步真实格式,以便更好地与 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(parameters) 而不是返回 this.cache[name]; 否则我会收到一个javascript错误..问题是如果我在第二次加载maps.json时将其更改为获取$.ajax(parameters),它不会从this.cache获取数据,它将加载json文件再次没有用

谁能帮忙

谢谢 :)

4

3 回答 3

1

$.ajax返回一个Deferred对象。你也可以返回你自己的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;
    }
}
于 2012-12-31T03:07:24.010 回答
0

两个建议:

  • 避免this参考AsyncLoader

  • Object.hasOwnProperty()用而不是测试对象属性的存在typeof .... == 'undefined'

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()不会尝试返回数据,至少不是传统意义上的;相反,它返回一个“承诺”,如果所需的数据已经从缓存中可用,则立即解决,或者稍后在服务器响应时解决。

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

例如 :

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

这样,目的就达到了。通过返回一个承诺(在 内创建AsyncLoader.load()),所需的数据在 的范围之外可用AsyncLoader.load(),以完全相同的方式,无论它是从缓存中提取还是从服务器新接收的。

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

于 2013-01-01T23:59:51.923 回答
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);

});

异步加载器

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 它工作正常,但我需要 async 为 true

谢谢

于 2012-12-31T04:30:18.507 回答