blog icon indicating copy to clipboard operation
blog copied to clipboard

更友好的操作 localStorage 与 sessionStorage

Open lmk123 opened this issue 9 years ago • 3 comments

2016.6.30 更新:

你可以使用 NamedStorage 来达成本文提出的优化。

原文

在修改存储在 localStorage 或 sessionStorage 里的数据时,最常用的大概就是下面的步骤了:

function modifyStorage (string) {
  // 先读取数据
  const data = JSON.parse(localStorage.getItem('arrayData'))
  // 修改数据
  data.push(string)
  // 重新保存
  localStorage.setItem('arrayData', JSON.stringify(data))
}

modifyStorage('new data')

但是这样做有些问题:

  • 每次修改数据时都调用了 localStorage 的 API。localStorage 与 sessionStorage 的 API 都是同步操作,频繁的调用 API 可能会造成性能低下(特别是在读取或设置很大的数据时)。
  • 数据对用户来说是可见的。打开 Chrome 开发者工具,切换到 “Resources” 面板,展开左侧的 “Local Storage”,你就会看到 'arrayData'。任何人都可以很方便的修改这个值——如果一个调皮的用户将你的数据结构给改了,你的应用可能就会因为报错而崩溃了。

所以,我在修改 storage 内的数据时是这样做的:

// 网页打开时读取一次
const data = JSON.parse(localStorage.getItem('arrayData'))
// 如果你不想让用户知道你存了些什么,那读取完后立刻删除
localStorage.removeItem('arrayData')
// 修改数据时只修改变量
function modifyStorage (string) {
  data.push(string)
}
// 重要的一步:网页关闭前将数据写入 storage
window.addEventListener('unload', () => localStorage.setItem('arrayData', JSON.stringify(data)))

modifyStorage('new data')

对比一下文章开头的代码,这样做的好处显而易见:

  • 从网页打开到关闭,我们最多只操作了三次 localStorage
  • 网页打开后,用户无法从 Chrome 开发者工具看到你保存了哪些数据。
  • 即使用户使用 Chrome 开发者工具破坏了你的数据结构,对你的应用也不会造成任何影响。

但需要注意的是,在一些奇怪的运行环境中(例如 Native App 的 WebView 里),unload 事件不一定会触发。这种情况下,你还是可以保证读取数据的操作只有一次:

// 网页打开时读取一次
const data = JSON.parse(localStorage.getItem('arrayData'))
// 因为 window.onunload 可能不会被触发,所以每次修改数据时都保存一次
function modifyStorage (string) {
  data.push(string)
  localStorage.setItem('arrayData', JSON.stringify(data))
}

modifyStorage('new data')

完。

lmk123 avatar May 23 '16 10:05 lmk123

哈哈,这个点子不错! 👍

cssmagic avatar May 30 '16 03:05 cssmagic

= =,所以每次修改数据时都保存一次,那不就是等于没有做优化吗?

kasinooya avatar Jun 06 '16 11:06 kasinooya

@kasinooya 至少数据只从 localStorage 里读取了一次,这比每次修改时都从 localStroage 里读取要好的多

lmk123 avatar Jun 06 '16 13:06 lmk123