在Javascript中加载图像时,iPad / iPhone浏览器崩溃 [英] iPad/iPhone browser crashing when loading images in Javascript

查看:443
本文介绍了在Javascript中加载图像时,iPad / iPhone浏览器崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Safari中构建一个模仿iPad照片应用的图片库。它工作得很好,除了我通过将它们添加到DOM或创建新的Image对象加载超过6MB左右的图像,新图像停止加载或浏览器崩溃。这个问题已经足够普遍了(其他人都遇到了相同的限制)我已经排除了我的Javascript代码作为罪魁祸首。

I'm trying to build an image gallery in Safari that mimics the iPad photo app. It works perfectly, except that once I load more than 6MB or so worth of images either by adding them to the DOM or creating new Image objects, new images either stop loading or the browser crashes. This problem is widespread enough (with everyone else hitting up against the same limit) that I've ruled out my Javascript code as the culprit.

鉴于你可以流多少在一个元素或浏览器内的媒体播放器中超过几MB,这个限制似乎是不必要的,应该有一些可用的解决方法。也许是通过释放内存或其他东西。

Given that you can stream much more than a few MB in a element or through the in-browser media player, this limit seems unnecessary, and there should be some kind of workaround available. Perhaps by freeing up memory or something else.

我也遇到了这个 UIWebView的参考

JavaScript分配也限制在10 MB。如果你在JavaScript的总内存分配上超过这个限制,Safari就会引发异常。

"JavaScript allocations are also limited to 10 MB. Safari raises an exception if you exceed this limit on the total memory allocation for JavaScript."

哪个匹配什么我看得很清楚。是否可以在Javascript中解除分配对象,或者Safari / UIWebView是否保持运行总计并且永远不会放手?或者,是否有任何解决方法以另一种方式加载数据而不吃掉这10MB?

Which matches what I'm seeing fairly well. Is it possible to deallocate objects in Javascript, or does Safari/UIWebView keep a running total and never lets go? Alternately, is there any workaround to load in data another way that doesn't eat up this 10MB?

推荐答案

更新:我认为根据您的应用,有一种更简单的方法可以做到这一点。如果您只有一个< img> 元素或图像对象(或者两个,比如'this'图像和'next'图像,如果你需要动画或过渡)并简单地更新 .src .width .height 等等,你永远不应该接近10MB的限制。如果您想要进行轮播申请,则必须先使用较小的占位符。您可能会发现此技术可能更容易实现。

Update: I think there's an even easier way to do this, depending on your application. Instead of having multiple images, if you simply have one <img> element or Image object (or maybe two, like a 'this' image and a 'next' image if you need animations or transitions) and simply update the .src, .width, .height and so on, you should never get near the 10MB limit. If you wanted to do a carousel application, you'd have to use smaller placeholders first. You might find this technique might be easier to implement.

我想我实际上可能找到了解决方法。

I think I may actually have found a work-around to this.

基本上,您需要进行更深入的图像管理并明确缩小您不需要的任何图像。你通常使用 document.removeChild(divMyImageContainer) $(myimagecontainer)。empty()或者你有什么,但在Mobile Safari上,这绝对没有;浏览器根本不会释放内存。

Basically, you'll need to do some deeper image management and explicitly shrink any image you don't need. You'd normally do this by using document.removeChild(divMyImageContainer) or $("myimagecontainer").empty() or what have you, but on Mobile Safari this does absolutely nothing; the browser simply never deallocates the memory.

相反,您需要更新图像本身,因此占用的内存非常少;您可以通过更改图像的 src 属性来实现。我所知道的最快捷的方法是使用数据网址。所以不要这样说:

Instead, you need to update the image itself so it takes up very little memory; and you can do that by changing the image's src attribute. The quickest way I know of to do that is to use a data URL. So instead of saying this:

myImage.src="/path/to/image.png"

...反而说:

myImage.src="data:image/gif;base64,AN_ENCODED_IMAGE_DATA_STRING"

下面是一个测试,以证明它的工作。在我的测试中,我的大型750KB图像最终会杀死浏览器并停止所有JS exectution。但是在重置 src 之后,我已经能够将图像的实例加载超过170次。下面也解释了代码的工作方式。

Below is a test to demonstrate it working. In my tests, my large 750KB image would eventually kill the browser and halt all JS exectution. But after resetting src, I"ve been able to load in instances of the image over 170 times. An explanation of how the code works is below as well.

var strImagePath = "http://path/to/your/gigantic/image.jpg";
var arrImages = [];
var imgActiveImage = null
var strNullImage = "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7";
var intTimesViewed = 1;
var divCounter = document.createElement('h1');
document.body.appendChild(divCounter);

var shrinkImages = function() {
    var imgStoredImage;
    for (var i = arrImages.length - 1; i >= 0; i--) {
        imgStoredImage = arrImages[i];
        if (imgStoredImage !== imgActiveImage) {
            imgStoredImage.src = strNullImage;
        }
    }
};
var waitAndReload = function() {
    this.onload = null;
    setTimeout(loadNextImage,2500);
};
var loadNextImage = function() {
    var imgImage = new Image();
    imgImage.onload = waitAndReload;
    document.body.appendChild(imgImage);
    imgImage.src = strImagePath + "?" + (Math.random() * 9007199254740992);
    imgActiveImage = imgImage;
    shrinkImages()
    arrImages.push(imgImage);
    divCounter.innerHTML = intTimesViewed++;
};
loadNextImage()

编写此代码是为了测试我的解决方案,所以你将拥有找出如何将它应用于您自己的代码。代码分为三部分,我将在下面解释,但唯一非常重要的部分是 imgStoredImage.src = strNullImage;

This code was written to test my solution, so you'll have to figure out how to apply it to your own code. The code comes in three parts, which I will explain below, but the only really important part is imgStoredImage.src = strNullImage;

loadNextImage()只需加载新图像并调用 shrinkImages()。它还分配了一个 onload 事件,该事件用于开始加载另一个图像的过程(bug:我应该稍后清除此事件,但我不是)。

loadNextImage() simply loads a new image and calls shrinkImages(). It also assigns an onload event which is used to begin the process of loading another image (bug: I should be clearing this event later, but I'm not).

waitAndReload()仅用于允许图像时间显示在屏幕上。移动Safari非常慢并且显示大图像,因此在加载图像后需要时间来绘制屏幕。

waitAndReload() is only here to allow the image time to show up on the screen. Mobile Safari is pretty slow and displaying big images, so it needs time after the image has loaded to paint the screen.

shrinkImages()遍历所有先前加载的图像(活动图像除外)并将 .src 更改为dataurl地址。

shrinkImages() goes through all previously loaded images (except the active one) and changes the .src to the dataurl address.

我在这里使用dataurl的文件夹图像(这是我能找到的第一个dataurl图像)。我只是使用它,所以你可以看到脚本工作。你可能想要使用透明的gif,所以请改用这个数据url字符串: data:image / gif; base64,R0lGODlhAQABAIAAAP /// wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw ==

I'm using a file-folder image for the dataurl here (it was the first dataurl image I could find). I'm using it simply so you can see the script working. You'll probably want to use a transparent gif instead, so use this data url string instead: data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==

这篇关于在Javascript中加载图像时,iPad / iPhone浏览器崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆