diff --git a/scripts/gulp/tasks/e2e.dev.ts b/scripts/gulp/tasks/e2e.dev.ts index 06087a5f4f..3df9694f5c 100644 --- a/scripts/gulp/tasks/e2e.dev.ts +++ b/scripts/gulp/tasks/e2e.dev.ts @@ -204,6 +204,10 @@ task('e2e.watch', ['e2e'], function () { watch('src/components/*/test/**/*', function (file) { start('e2e.build'); }); + + watch('scripts/workers/**/*', function (file) { + start('e2e.workers'); + }); }); function watchTask(task) { diff --git a/scripts/workers/ion-img-worker.js b/scripts/workers/ion-img-worker.js index 4804a05103..405eec36e7 100644 --- a/scripts/workers/ion-img-worker.js +++ b/scripts/workers/ion-img-worker.js @@ -1,29 +1,41 @@ (function(){ + // keep a collection of all the + // cached images and current image requests var imgs = []; - var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - var cacheLimit = 1381855 * 10; + + // set the cache limit, about 20MB + var cacheLimit = 1381855 * 20; onmessage = function(msg) { + // received a message from the main thread + // message was a string, JSON parse it var msgData = JSON.parse(msg.data); var id = msgData.id; var src = msgData.src; var imgData; + // see if we already have image data for this src for (var i = 0; i < imgs.length; i++) { if (imgs[i].s === src) { + // found existing image data imgData = imgs[i]; break; } } if (msgData.type === 'abort') { + // this message was to abort this src if (imgData && imgData.x) { + // we found the image data and there's + // an active request, so let's abort it imgData.x.abort(); imgData.x = null; } } else if (msgData.cache && imgData && imgData.d) { + // we found image data, and it's cool if we use the cache + // so let's respond to the main thread with the cached data postMessage(JSON.stringify({ id: id, src: src, @@ -33,7 +45,11 @@ })); } else { + // we need to do a full http request + if (imgData && imgData.x && imgData.x.readyState !== 4) { + // looks like there's already an active http request + // for this same source, so let's just add another listener imgData.x.addEventListener('load', function(ev) { onXhrLoad(id, src, imgData, ev); }); @@ -44,25 +60,33 @@ } if (!imgData) { + // no image data yet, so let's create it imgData = { s: src, c: msgData.cache }; imgs.push(imgData); } + // ok, let's do a full request for the image imgData.x = new XMLHttpRequest(); imgData.x.open('GET', src, true); imgData.x.responseType = 'arraybuffer'; + + // add the listeners if it loaded or errored imgData.x.addEventListener('load', function(ev) { onXhrLoad(id, src, imgData, ev); }); imgData.x.addEventListener('error', function(e) { onXhrError(id, src, imgData, e); }); + + // awesome, let's kick off the request imgData.x.send(); } }; function onXhrLoad(id, src, imgData, ev) { + // the http request has been loaded + // create a rsp object to send back to the main thread var rsp = { id: id, src: src, @@ -72,16 +96,25 @@ }; if (ev.target.status === 200) { + // success!! + // now let's convert the response arraybuffer data into a datauri setData(rsp, ev.target.getResponseHeader('Content-Type'), ev.target.response); rsp.len = rsp.data.length; } + // post back to the main thread what we've learned today postMessage(JSON.stringify(rsp)); if (imgData.x.status === 200 && imgData.c) { + // if the image was successfully downloaded + // and this image is allowed to be cached + // then let's add it to our image data for later use imgData.d = rsp.data; imgData.l = rsp.len; + // let's loop through all our cached data and if we go + // over our limit then let's clean it out a bit + // oldest data should go first var cacheSize = 0; for (var i = imgs.length - 1; i >= 0; i--) { cacheSize += imgs[i].l; @@ -93,17 +126,20 @@ }; function onXhrError(id, src, imgData, e) { + // darn, we got an error! postMessage(JSON.stringify({ id: id, src: src, - status: 510, - msg: e.message + '' + e.stack + status: 0, + msg: (e.message || '') })); imgData.x = null; }; function setData(rsp, contentType, arrayBuffer) { + // take arraybuffer and content type and turn it into + // a datauri string that we can pass back to the main thread rsp.data = 'data:' + contentType + ';base64,'; var bytes = new Uint8Array(arrayBuffer); @@ -136,4 +172,7 @@ } } + // used the setData function + var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + })(); diff --git a/src/components/img/img.ts b/src/components/img/img.ts index dc1b3b697e..fa8bfa606e 100644 --- a/src/components/img/img.ts +++ b/src/components/img/img.ts @@ -273,7 +273,9 @@ export class Img implements OnDestroy { } else { // error :( - console.error(`img, status: ${msg.status} ${msg.msg}`); + if (msg.status) { + console.error(`img, status: ${msg.status} ${msg.msg}`); + } this._renderedSrc = this._tmpDataUri = null; this._dom.write(() => { this._isLoaded(false);