Javascript: How to check if image is already cached - javascript

I just started to learn a little bit of JavaScript and i wondered if there is a way to check if an image is already loaded to cache.
In my script im loading some random images from another webpage and display them.
When the same image will be displayed the second time, the script won't use the already loaded image, but instead load the same image again, so that there are two of them stored in my cache.
Now I want to check if the image is already stored in cache and if so, use the cached one instead of loading it again.
My code:
<script>
var img = document.createElement('img');
var index;
//On Click create random 3digit number between 1 and 100
document.getElementById('image').onclick = function(){
var index = '' + Math.floor(Math.random() * 100 +1);
while(index.length < 3) {
index = '0' + index;
}
loadImages(index);
};
//Load the image with the created number
function loadImages(id) {
var src = 'someWebPage/' + id +'.png';
img.onload = function () {
document.getElementById('image').getContext("2d").drawImage(img, 0, 0, 300, 300);
}
img.src = src;
}
</script>
Picture of my cache:
As you can see 030.png and 032.png are twice in cache.
Hope you can give me some advice.
EDIT:
Just for anyone else that faces this problem, it actually isnĀ“t one at all.
Chrome already did everything right, i only did not notice.
As you can see in the column Size the pictures were already loaded from my cache.

The way caching (in this context) is handled is by the browser negotiating with the server using a set of headers to basically tell the server "I already have this version of this resource", to which the server can then respond "OK, that is still valid, no need to download anything new". So you shouldn't be concerned about the caching in the JavaScript side, but instead make sure you are setting the correct Cache-Control headers on the server side. There are likely already questions/answers for your server/framework of choice on how to setup the caching there.

Related

Adding img.crossOrigin = "*" interferes with img.complete

I have a function that reads map tile images. I want to keep track of whether or not a certain image has already been cached. I'm using this function from this thread:
function is_cached(src) {
var image = new Image();
image.src = src;
return image.complete;
}
This was working great. But then I needed to do some image processing. In order to copy the image data to a canvas and process it pixel by pixel, I need to use CanvasRenderingContext2D.drawImage(image, 0, 0). But it bugs me with a cross-origin error. So I can add a image.crossOrigin = "*", which solves that problem, and I can write to a canvas and do the image processing I need. That bit looks like this:
imageOutput.crossOrigin = "*"
var demCtx;
imageOutput.onload = function(){
var c = document.createElement('canvas')
c.width = c.height = 256
demCtx = c.getContext('2d')
demCtx.drawImage(imageOutput, 0, 0)
var imageData = demCtx.getImageData(0, 0, 256, 256)
}
The issue that arises is that every time I run the larger function which contains these two bits of code, the is_cached function returns false every time, except the first time. But I know that even though is_cached is returning false, the images are indeed cached, as they are loading with 0 lag (as opposed to when a novel image is called and it takes a moment to grab it from the server).
Why might .crossOrigin = "*" be interfering with the .complete status of an image?
This is happening within an ObservableHQ notebook. Might that have something to do with it? ObservaleHQ gets weird sometimes.
ObservableHQ Notebook with the problem
You can find this code in the getTileUrl cell at the bottom. This notebook is not yet finished. You can see the cached status at the Tile Previously Cached line after you click around the map of submit changes to the inputs.
Thanks for reading.
Maybe fetch api can enforce cache using the param {cache:"force-cache"}, however images should be cached as expected. You can fetch the image and pass its blob as an image source.
replace your imageOutput.src with
imageOutput.src = URL.createObjectURL(await fetch(imageUrl, {cache:"force-cache"}).then(r => r.blob()));
make your getTileURL function async as we have to await fetch and blob to be ready to be passed as image source
async function getTileURL(latArg, lngArg, zoomArg) {
Use devtools to inspect network and see tile images coming from disk cache
edit:
just try your original code and inspect network via devtools. The tiles images are cache as expected. So no need to hack into fetch blob src.

Programm that tracks changes on web page

I have a web page that has several images on it and a script in it which changes picture of one random image once in some time interval. Script changes the image by rewtiting its file in the cash an updating it on the page. So url of the image picture doesnt chage in html code:
socket.on("banner", function(info) {
banName = "banner" + info.bid;
ban = document.getElementById(banName).getContext('2d');
var img = new Image();
img.src = 'data:image/jpg;base64,' + info.image;
img.onload = function(){ban.drawImage(img, 0, 0);};
});
How can I track image change using for example C#, when the page is in the browser?
As a last resort, retrieve the image periodically and load it into a byte array. Checking changes is just a matter of checking if the byte array has changed.
edit:
It seems the hard part is about how can one retrieve the image data. Without any javascript code in the browser, use C# to establish a websocket connection to mimic the behavior of javascript.
But I think it would be easier done by modifying the javascript code in the browser.

Html2canvas: facebook plugin comments

I have a website witch uses facebook plugin comments. I'm looking for a way to have those comments inside a screenshot. If I use the simple html2canvas I get a blank box instead of them. So I try to use html2canvasproxy but now it print some javascript console log instead of the facebook comments.
It shoud be like but I get . I noticed that the html2canvasproxy.php saves the facebook plugin html correctly.
I can't find any javascript error in the console log.
I'm using the following code to take the screenshot:
html2canvas(document.body, {
"logging": true, //Enable log (use Web Console for get Errors and Warnings)
"proxy":"js/html2canvasproxy.php",
"onrendered": function(canvas) {
var img = new Image();
img.onload = function() {
img.onload = null;
document.body.appendChild(img);
};
img.onerror = function() {
img.onerror = null;
if(window.console.log) {
window.console.log("Not loaded image from canvas.toDataURL");
} else {
alert("Not loaded image from canvas.toDataURL");
}
};
img.src = canvas.toDataURL("image/png");
}
});
And I have this settings in html2canvasproxy.php:
//Turn off errors because the script already own uses "error_get_last"
error_reporting(0);
//setup
define('JSLOG', 'console.log'); //Configure alternative function log, eg. console.log, alert, custom_function
define('PATH', '../screenshots');//relative folder where the images are saved
define('CCACHE', 60 * 5 * 1000);//Limit access-control and cache, define 0/false/null/-1 to not use "http header cache"
define('TIMEOUT', 30);//Timeout from load Socket
define('MAX_LOOP', 10);//Configure loop limit for redirect (location header)
define('CROSS_DOMAIN', 0);//Enable use of "data URI scheme"
//constants
define('EOL', chr(10));
define('WOL', chr(13));
define('GMDATECACHE', gmdate('D, d M Y H:i:s'));
First idea I got while reading is to include some timeout - waiting a bit longer (let's say 200ms) - so that you have more probability for things to get loaded.
But after reading this on plugin site: "The script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page." it could not help.
Personally I would investigate using another solution - like for example PhantomJS:
"PhantomJS is a headless WebKit scriptable with a JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG."
It's easy like this:
var page = require('webpage').create();
page.open('http://github.com/', function() {
page.render('github.png');
phantom.exit();
});

jQuery $.get() Memory Usage

This is the jQuery method that I have at my webpage, it refreshes a image every 5 seconds by loading the same page and replacing the image.
$(document).ready(function () {
var refreshId = setInterval(function () {
$.get('default.aspx', function (data) {
var page = data;
var image = $(page).find("img");
var fecha = $(page).find("div #fecha");
$("#Chart1").attr("src", image.attr("src"));
$("#fecha").text(fecha.text());
});
}, 5000);
});
I saw that everytime it loads the img, the data get stored somewhere in the browser and it doesnt cleans.. And when I open the task manager, I can see the memory usage growing up..
and heres a screenshot of the image axd..
Should I worry about freeing memory? Or everything is working as its supposed to..
why not reload the image by using just the url and not fetch the whole page that gets the url? if you want to prevent cache, either set the image not to cache via server headers, or use cachebusting
var img = document.getElementById('Chart1'); //use plain JS since it's just an ID
var refreshId = setInterval(function () {
var rand = "?"+(Math.random()*10000000000000000); //cache busting method
img.src = "path_to_image"+rand //set src using busted url
}, 5000);
this will still eat up disk space since each busted images is treated like a different image. if it were cached, you'd be using stale images. but at least you are not loading the whole page again an again.
Found out that the browser is just caching the images, but they are being cleaned eventually.
Use $post instead of $get. IE often cash GET request data.
There is just one img#Chart1 in your page, so there is only one image uses memory.
Others would just in the browser's cache.
But I don't think that default.aspx return in html format,
it should return data in json like:
{
imageUrl: "http://example.com/a.jpg",
fetcha: "some text"
}

Getting size of javascript preloaded image

I'm trying to preload a number of images generated on the server to a small website. The preloading is done using setWindowTimeout and uses an Image object, sets the onload callback and then applies the new request uri.
For some requests, the server may have to signal that the image is 'unchanged' and I'm doing it by sending done a small 1x1 pixel gif (seems like I need to send an actual image, returning empty content will cause the Image object to not fire onload). In my onload handler I would like to determine the size of the fetched image and then determine if I should update the visual image with the given image.
Below is a snippet of my current solution (the output is a div to help debug):
refresh: function() {
var newSrc = '/screenshot.ashx?tick=' + new Date().getTime();
var imgObj = new Image();
var self = this;
// this is called when load is done
imgObj.onload = function() {
//if (imgObj.complete)
// return;
if (imgObj.width > 1 && imgObj.height > 1) {
output.innerHTML += '<br/>Updating image:' + newSrc;
img.src = newSrc; //fiddler shows no reload here, read from cache
}
else {
output.innerHTML += '<br/>Empty image:' + newSrc;
}
self.setupNewRefresh();
};
output.innerHTML += '<br/>Loading image:' + newSrc;
imgObj.src = newSrc;
},
I seem to have two problems:
a) the imgObj.complete is false when the function is first called but it is only called once (hence my commenting it out) and
b) I can't seem to rely on the width or height property of the image when loaded. From my tests of fetch the 1x1 pixel, it sometimes reads out 50 which seems to be default when creating a new Image() and it sometimes reads out the correct size of 1.
My ultimate goal is to have a small chunk of javascript logic that queries the server for a new image periodically, does nothing if nothing new has happened (1 pixel image) or loads the new image. I might be going about it the wrong way here or have overlooked important properties or calls, so I'm happy to receive feedbacks.
EDIT: upon suggestion from mplungjan, I preloaded into a hidden div instead, which helped me with problem b). Still no solution to problem a) though; reports complete = false once and is not called again
I'll go ahead and answer my own question.
Preloading the image into a hidden element in the DOM instead of a code-level element was the trick for actually getting correct sizes (thanks mplungjan). The a) issue, namely the complete event, remains unsolved.
As a side note I ended up using the XMLHttpRequest instead as it allowed by to look at the size of the payload returned.

Categories

Resources