【问题标题】:preload image with ajax用ajax预加载图片
【发布时间】:2012-06-06 07:46:33
【问题描述】:

http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/找到这种使用 ajax 预加载内容的技术

window.onload = function() {
    setTimeout(function() {
        // XHR to request a JS and a CSS
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.js');
        xhr.send('');
        xhr = new XMLHttpRequest();
        xhr.open('GET', 'http://domain.tld/preload.css');
        xhr.send('');
        // preload image
        new Image().src = "http://domain.tld/preload.png";
    }, 1000);
};

我注意到此图像的“ajax”预加载根本不是真正的 ajax。它和我多年来一直使用的一样,只是将 url 设置在新图像对象的源中,然后让浏览器将其加载到缓存中。

现在假设有一个应用程序,如果它占用了一定的时间,我需要实际取消图像的预加载。仅将图像设置为 src 确实没有什么好的方法,这与停止加载实际 xhr 请求的 xhr.abort() 方法不同。

是否有任何原因导致执行以下操作不能很好地预加载图像并允许取消预加载请求?

function preload(url, timeout){
    this.canceltimeout = function(){
        clearTimeout(this.timeout);
        this.loaded = true;
        return false;
    }

    this.abort = function(){
        this.xhr.abort();
        this.aborted = true;
    }

    //creates a closure to bind the functions to the right execution scope
    this.$_bind = function(method){
        var obj = this;
        return function (e){ obj[method](e);};
    }

    //set a default of 10 second timeout
    if(timeout == null){
        timeout = 10000;
    }

    this.aborted = false;
    this.loaded = false;
    this.xhr = new XMLHttpRequest();
    this.xhr.onreadystatechange = this.$_bind('canceltimeout');
    this.xhr.open('GET', url);
    this.xhr.send('');
    this.timeout = setTimeout(this.$_bind('abort'), timeout);
}

var llama = new preload('/image.gif');
show_image();

function show_image(){
    if(llama.loaded){
        var l = new Image();
        l.src = '/image.gif';
        application.appendChild(l);
    }else if(llama.aborted){
        var l = document.createElement('p');
        l.innerHTML = 'image.gif got cancelled';
        application.appendChild(l);
    }else{
        setTimeout(show_image, 10);
    }
    return false;
}

【问题讨论】:

  • 使用 jquery man。 api.jquery.com/jQuery.ajax
  • 可以使用 jquery,但这与使用 xhr 对象请求图像是否足以将其加载到缓存中没有任何关系。 Jquery 相当庞大,当您只需要它的一小部分时,它真的无济于事。
  • 我看到我发布的 show_image 函数有点乱。 application 是来自其他一些 javascript 的全局变量,我将这段代码添加到其中以进行尝试。它似乎有效,但我没有很多不同的浏览器或关于它们的缓存的知识可以从中提取,看看这是否可以跨浏览器的方式工作。
  • 它可能不起作用的一个原因是由于跨域策略,此外它看起来不错。
  • 不用担心跨域政策,因为网站上所有考虑过这一问题的图片都是直接从我们的服务器提供的,但即使没有,您也可以通过一点服务器端脚本魔法轻松解决这个问题如果调用的是服务器端脚本而不是图像,则检索图像并将其返回。

标签: javascript ajax image preload


【解决方案1】:

主要缺点是除非您已将网络服务器配置为提供未来的新鲜度信息(ExpiresCache-control: max-age 未来的 http 标头),否则网络浏览器可能会向服务器发出第二个 http 请求当您设置 image.src,或者只是简单地实际使用文档中的图像时。如果您的 Web 服务器发送了新鲜度验证标头(last-modifiede-tag),则不会重新下载图像,但仍会发出请求服务器进行新鲜度验证的请求,这很浪费并增加了延迟过程。

我不知道为什么,但是浏览器确实喜欢在您持有对 Image() 对象的引用时缓存图像。

如果您在网络浏览器调试工具中观看网络面板,您会发现大多数浏览器会发出前 2 个请求,但不会发出第 3 个请求。注释掉 ajax 回调中的代码,您将看到针对 #3 的请求

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script>
<script>
var f = "0.png?" + (new Date); // 0.png should not have future freshness info headers

$.get(f, function() {
    var i = new Image();
    i.src = f;
});
setTimeout(function(){
    //#3
    var i = new Image();
    i.src = f;
}, 5000);
</script>

【讨论】:

  • 在我的实际服务器上,图像由 php 脚本动态调整大小和水印,因此很容易为它们提供所有正确的缓存控制标头。动态地完成所有这些需要一些额外的时间,但是客户非常担心有人窃取他们的图片,因此我实施的预加载以及调整大小版本的服务器端缓存似乎是减轻延迟造成的延迟的最佳方法这整个过程。感谢您的洞察力。
猜你喜欢
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2012-02-04
  • 1970-01-01
  • 2017-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多