JavaScript: как заставить Image() не использовать кеш браузера?

Если я загружаю URL nextimg вручную в браузере, он дает новое изображение при каждом перезагрузке. Но этот бит кода показывает одно и то же изображение на каждой итерации draw().

Как я могу заставить myimg не кэшироваться?

<html>
  <head>
    <script type="text/javascript">
      function draw(){
        var canvas = document.getElementById('canv');
        var ctx = canvas.getContext('2d');
        var rx;
        var ry;
        var i;

        myimg = new Image();
        myimg.src = 'http://ohm:8080/cgi-bin/nextimg'

        rx=Math.floor(Math.random()*100)*10
        ry=Math.floor(Math.random()*100)*10
        ctx.drawImage(myimg,rx,ry);
        window.setTimeout('draw()',0);
      }
    </script>
  </head>
  <body onload="draw();">
    <canvas id="canv" width="1024" height="1024"></canvas>
  </body>
</html>

Ответ 1

На самом деле это звучит как ошибка в браузере - вы можете записать в http://bugs.webkit.org, если он находится в Safari или https://bugzilla.mozilla.org/ для Firefox. Почему я говорю о возможной ошибке браузера? Поскольку браузер понимает, что он не должен кэшироваться при перезагрузке, все же он дает вам кешированную копию изображения, когда вы запросите его программно.

Тем не менее, вы уверены, что на самом деле рисуете что-нибудь? API Canvas.drawImage не будет ждать загрузки изображения и не будет рисовать, если изображение не было полностью загружено, когда вы пытаетесь его использовать.

Лучшая практика - это что-то вроде:

    var myimg = new Image();
    myimg.onload = function() {
        var rx=Math.floor(Math.random()*100)*10
        var ry=Math.floor(Math.random()*100)*10
        ctx.drawImage(myimg,rx,ry);
        window.setTimeout(draw,0);
    }
    myimg.src = 'http://ohm:8080/cgi-bin/nextimg'

(Вы также можете просто передать draw как аргумент для setTimeout, а не использовать строку, которая сохранит повторную и повторную сборку одной и той же строки снова.)

Ответ 2

Самый простой способ - перебросить постоянно меняющуюся строку запроса:

var url = 'http://.../?' + escape(new Date())

Некоторые люди предпочитают использовать Math.random() для этого вместо escape(new Date()). Но правильным способом, вероятно, является изменение заголовков, отправляемых веб-сервером, чтобы запретить кэширование.

Ответ 3

Вы не можете остановить его от кэширования изображения в целом в Javascript. Но вы можете играть с src/адресом изображения, чтобы заставить его кэшировать заново:

[Image].src = 'image.png?' + (new Date()).getTime();

Возможно, вы можете взять любой из решений кеша Ajax и применить его здесь.

Ответ 4

На самом деле есть два кеша, которые нужно обойти здесь: один - это обычный HTTP-кеш, который можно избежать, используя правильные заголовки HTTP на изображении. Но вы также должны остановить браузер от повторного использования копии копии в памяти; если он решит, что он может сделать это, он даже не дойдет до запроса своего кеша, поэтому заголовки HTTP не помогут.

Чтобы предотвратить это, вы можете использовать либо переменную строку запроса, либо изменить идентификатор фрагмента.

См. мой пост здесь для более подробной информации.