前端 ajax 加载缓存方案 —— 图片强制缓存

前端 ajax 加载缓存方案 —— 图片强制缓存

前言

上一篇 写了关于前端如何缓存 ajax 加载的数据,如果对这个话题感兴趣又没有看过的童鞋,不妨前去一观:https://blog.csdn.net/lovefengruoqing/article/details/103780958

这一篇文章是上一篇文章的后续,所以,如果没看过上一篇文章的话,有些内容可能理解起来,还是有点障碍的,因为有些前置的内容,这篇文章不会细讲,而是会直奔主题。

很多时候,浏览器会强制对页面里面的静态资源进行缓存,以提升页面的二次加载速度。

当然这种说法,其实是不太准确的,因为我们是可以通过多种方式来控制这种“浏览器默认的缓存机制”。

既可以通过在 html 的 head 中加标签来控制,也可以通过在后端响应前端的请求的响应头中设置参数来控制。

如果想详细研究的话,请参考 stackoverflow 上的相关讨论,已经很详细了:https://stackoverflow.com/questions/49547/how-do-we-control-web-page-caching-across-all-browsers

这种浏览器默认的缓存的机制,其实是不可靠的,因为对于我们来说,不是完全可控的。

如果我们想要一种完全可控的前端图片缓存机制,我们该如何做呢?

别着急,耐心往下看,你就明白应该怎么处理了。

前端默认加载图片的几种方式

我们知道的是,默认情况下,我们加载图片,都是借助 html 标签来加载的,我们一般的做法有几种:

1. html 方式

直接写在 html 代码中,将 img 标签的 src 设置为我们图片的路径。

<img src="https://www.baidu.com/img/bd_logo1.png">

2. JavaScript 方式

通过创建一个 Image 对象的实例,然后将该实例的 src 属性设置为我们图片的路径。

var img = new Image();
img.src = 'https://www.baidu.com/img/bd_logo1.png';
img.onload = () => {
	console.log('图片加载完成✅!');
}

上面 👆 这两种方式,都不是我们可控的。

因为这两种方式,有个共同点,都不是通过 ajax 方式加载的,而是浏览器引擎解析了以后,自动请求的。

打开 devtools,你就会明白这种说法是什么意思。

image.png

但是如果,我们将图片的加载完全改成 ajax 加载,那么我们就可以完全控制,是否需要对图片做缓存了。

但是如何做呢?

缓存用我们上一篇文章的中的 IndexedDB 就可以实现,但是我们如何 🤔️ 通过 ajax 的方式,来加载图片呢?

如果你没尝试过,那么接下来,我会提供几种可行的方案。

当然,fetch 会遇到

ajax 加载图片

这里我们借助 fetch 这个 api,来方便我们发送 ajax 请求。

fetch(imgUrl);

然后我们可以通过 then,拿到请求到的对象,但是这个对象需要封装成文件,我们才能使用。

fetch(imgUrl)
  .then(response => response.blob());

1. URL.createObjectURL

然后再通过 then 的链式调用,拿到封装后的文件对象。

在这种方式,我们通过 URL.createObjectURL 这个 api,对拿到的文件对象进行封装,封装了以后,会返回一个新的 url 对象,这个对象可以理解为我们浏览器中的该对象的引用或者指针,就是指代该对象的。

如果不了解 URL.createObjectURL,可以参考下该页面:https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL

fetch(imgUrl)
  .then(response => response.blob())
  .then(blob => {
    var imgUrl = URL.createObjectURL(blob);
    callback(imgUrl);
  });

如果不理解为什么要这么用,可以参考下面这个在 input 选择图片上传的过程中预览图片的小 demo:https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications#Example_Using_object_URLs_to_display_images

2. base64 格式

base64 也是一种常见用来存储图片的格式,我们可以借助其将图片编码为字符串,便于我们存储在数据库或者代码之中。

我们当然也可以借助 base64 的方式,来存储我们通过 ajax 方式请求到的图片。

我们直接将获取到的 blob 文件,通过 FileReader 对象上的 readAsDataURL 这个 api,将其读取成 base64 格式的图片。

fetch(imgUrl)
  .then(response => response.blob())
  .then(blob => {
    const fileReader = new FileReader();
    fileReader.onload = (e) => {
      var base64 = e.target.result;
      console.log(base64);
    };
    // readAsDataURL
    fileReader.readAsDataURL(blob);
    fileReader.onerror = () => {
      console.error(new Error('blobToBase64 error'));
    };
  });

理清楚了这个思路以后,接下来,就可以接着上一篇文章的思路来了。

我们直接将 blob 存储在 IndexedDB 数据库中,我们借助 read 从 imagePool 这个表中读取我们请求的 url,当读取成功了,就证明这个文件我们曾经读取过,属于二次加载。

那么我们 then 的 resolve 方法中就会被调用,否则 reject 方法就会被调用。

const resolve = (data) => {
  callback(URL.createObjectURL(data));
}

const reject = () => fetch(url)
  .then(response => response.blob())
  .then(blob => {
    add(blob, url, 'imagePool');
    var imgUrl = URL.createObjectURL(blob);
    callback(imgUrl);
  });

function getImageByXHR(url, callback) {
  read(url, 'imagePool')
    .then(
      reslove,
      reject
    )
    .catch(function(err) {
      console.log(err);
    });
}

当然,就像我们之前讲过的那样,凡事都有利弊,需要合理的衡量利弊。

在性能和内存占用以及兼容性之间,找到一个合适的平衡点,足以。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值