Javascript:从没有base64-dataURL的自定义API将许多图像加载到DOM中

Javascript: Loading many images into DOM from a custom API without base64-dataURLs

本文关键字:图像 许多 加载 DOM API 自定义 base64-dataURL Javascript      更新时间:2023-09-26

Contexst:我目前正在使用Angular构建一个web-app,并使用Silex编写API。

我有以下情况:

  • 一个有数百个可点击缩略图的Angular页面。点击后,灯箱插件打开全尺寸图像
  • API需要一个自定义的token-header来加载每张图片

很好,我想,我制作了API,所以它以base64编码的方式返回图像。很简单。将这个base64编码的数据设置为图像源甚至更简单:src = "data:image/jpeg;base64," + response;。这是使用ngSrc完成的,使其有点异步。lightbox使用锚标记的href从中加载图像(我使用Colorbox(,因此每张照片我都有两个相当大的base64数据URL。

然而,这造成了严重的问题。不是只有一张照片就立即出现,而是当照片数量开始增加时。随着base64 URL保留在DOM中,浏览器选项卡开始需要越来越多的内存。

我为此创建了一个临时解决方案,创建了一种自定义的Silex控制器,该控制器不从头部读取令牌,而是从查询字符串读取令牌。这允许我将图像源设置为类似于src = "http://api/img/1?token=" + token;的内容。数据URL及其内存饥饿的问题已经不复存在。

然而,将来API很可能会开始需要HTTP基本身份验证来获取图像。并且基本身份验证凭据不能通过查询字符串传递。它们需要标头才能发挥作用。因此,我的变通方法将不再有效。因此,这是一个真正的临时解决方案。

不过,我不完全确定如何解决这个问题。需要通过Ajax调用加载图像才能添加自定义标头。整个过程必须是异步的,以便加载尽可能快。加载图像后,无论显示多少图像,都不应该占用内存,或者至少不会占用太多内存来保持页面的性能。

我一直在考虑将基于base64的图像加载到canvas元素上。类似这样的东西:

$scope.loadThumbnails = function() {
  $scope.photos.forEach(function($photo){
    $photo.canvas_th = document.querySelector('canvas#' + $photo.id + '_th');
    var request = $http({                                                                               
      method: "GET",                              
      url: [URL]                                     
    });                                                                                                 
    var fetchThumbnailSuccess = function(response) {                                                    
      console.debug("Fetched thumbnail with id " + $photo.id);
      // Get drawing context
      var ctx = $photo.canvas_th.getContext("2d");
      // Create image with onload drawing to context
      var img = new Image();
      img.onload = function() {
        ctx.drawImage(img, 0, 0);
      }
      // Add data to image object, triggering the onload function which in turn draws the image to the context
      img.src = 'data:image/jpeg;base64,' + response;
    }                                                                                                   
    request.success(fetchThumbnailSuccess);                                                             
    var fetchThumbnailFailure = function(response) {                                                    
      console.error("Failed fetching thumbnail with id " + $photo.id);                                
      console.debug(response);                                                                        
    }                                                                                                   
    request.error(fetchThumbnailFailure);                                                               
  });                                                                                                     
}

然而,我不确定这是否会更具表演性。然而,我相信其他人以前一定也遇到过这种情况。我是不是忽略了什么?做了完全错误的事情?我很想得到一些帮助,因为我目前正忙于我不那么花哨的变通方法。。。任何人

Canvas显示图像的内存与img元素一样多,因此使用Canvas不会解决内存问题。

只要你在积累编码的url来存储你的图像数据,你就会被不断增加的内存需求所困扰。

考虑到你目前灯箱的局限性,也许"自己滚动"会给你更好的性能。

只提供初始显示的缩略图,然后将单个全尺寸img元素的.src属性更改为所选缩略图的url,怎么样。

这样一来,你只会占用缩略图显示和单个全尺寸图像的内存。让浏览器缓存完整大小的图像,这样,如果用户重新查看以前的完整大小图像,它将快速从缓存中提取,而不是重新下载。