内置网络模块:如何使用 KV 存储

KV 存储的发布对 Web 平台来说是一个大问题,它是 Standard Library Proposal的一部分,它可能会为 JavaScript 引入更广泛的标准库。

在谈到什么是kv存储之前,让我们先讨论如何在浏览器中存储数据. 如果我现在想存储一些本地数据,我的主要选项之一将是使用 localStorage

考虑到这一点,让我们用JavaScript创建一个简单的Todo应用程序,利用localStorage,我们需要两个文件:index.html和main.js:

 1[label main.js]
 2const TODOS_KEY = 'todos';
 3const ul = document.getElementsByTagName('ul')[0];
 4
 5const showExistingTodos = todos => {
 6  if (todos.length > 0) {
 7    todos.map(todo => {
 8      addLi(todo);
 9    });
10  }
11};
12
13const addTodo = () => {
14  const input = document.getElementById('todoInput').value;
15
16  if (input.length > 0) {
17    addLi(input);
18    saveTodo(input);
19
20    document.getElementById('todoInput').value = '';
21  }
22};
23
24const addLi = text => {
25  const li = document.createElement('li');
26
27  li.appendChild(document.createTextNode(text));
28
29  ul.appendChild(li);
30};
31
32const saveTodo = todo => {
33  let loadedTodos = loadTodos();
34
35  loadedTodos = [...loadedTodos, todo];
36
37  localStorage.setItem(TODOS_KEY, JSON.stringify(loadedTodos));
38};
39
40const loadTodos = () => {
41  const todos = JSON.parse(localStorage.getItem(TODOS_KEY));
42
43  return todos != null ? todos : [];
44};
45
46const clearTodos = () => {
47  localStorage.removeItem(TODOS_KEY);
48
49  const todos = Array.from(document.getElementsByTagName('li'));
50
51  todos.map(todo => ul.removeChild(todo));
52};
53
54const todos = loadTodos();
55
56showExistingTodos(todos);
 1[label index.html]
 2<!DOCTYPE html>
 3<html lang="en">
 4<head>
 5  <meta charset="UTF-8">
 6  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 7  <meta http-equiv="X-UA-Compatible" content="ie=edge">
 8  <title>Document</title>
 9</head>
10<body>
11  <div>
12    <input id="todoInput" type="text" />  
13    <button onclick="addTodo()">Add Todo</button>
14    <button onclick="clearTodos()">Clear todos</button>
15  </div>
16
17  <ul>
18
19  </ul>
20
21  <script src="main.js"></script>
22</body>
23</html>

虽然这绝对可以改进,但我们现在有一个应用程序,我们可以用作例子. 如果我们尝试添加一些Todo项目,然后刷新页面,我们会看到它们立即出现!

Hmm...我做了一些研究,发现‘localStorage’是同步的,这对我们的应用意味着什么?

基本上,这意味着调用LocalStorage将阻止 DOM 内部的渲染,如果我们在LocalStorage中有大量元素,这可能会产生问题,并且会显著影响性能。

让我们来看看一个名为 KV 存储的实验内置模块(用于密钥/值存储)。

为什么不使用IndexedDB本地?

使用 KV 存储为我们提供了更直观的 API,类似于localStorage。我们也不需要转向第三方 IndexedDB 库,我们现在可以直接从浏览器中使用它!

KV 存储

对于这个例子,我们需要在Chrome中启用实验功能,然后在Chrome浏览器中导航到以下地址:

<$>[注] 在实验网页平台功能上选择启用: chrome://flags/#enable-experimental-web-platform-features

使用 Chrome Canary用于任何实验或新 Web 功能也是一个好主意。

现在我们将需要执行以下更新:

index.html中,导入main.js作为模块:

1<script type="module" src="main.js"></script>

接下来,我们可以更新我们的saveTodo函数以使用storage.set()而不是localStorage.setItem()

1const saveTodo = async todo => {
2  let loadedTodos = await loadTodos();
3
4  loadedTodos = [...loadedTodos, todo];
5
6  await storage.set(TODOS_KEY, loadedTodos);
7};

我们的loadTodos函数使用storage.get()而不是localStorage.getItem():

1const loadTodos = async () => {
2  const todos = await storage.get(TODOS_KEY);
3
4  return todos != null ? todos : [];
5};

<$>[注]请注意,我们如何轻松地使用 async/await 函数来处理非同步性。


最后,我们可以通过使用storage.delete()而不是localStorage.removeItem()来改进我们的clearTodos函数:

1const clearTodos = () => {
2  storage.delete(TODOS_KEY);
3
4  const todos = Array.from(document.getElementsByTagName('li'));
5
6  todos.map(todo => ul.removeChild(todo));
7};

我们还需要将这些暴露在窗口对象中:

1window.addTodo = addTodo;
2window.clearTodos = clearTodos;

我们的应用程序现在再次工作,但而不是LocalStorage,它使用了std:kv-storage内置的Web模块。

这意味着一切都是无同步的(正如我们的无同步等待承诺呼叫所指)。

客户支持

如果浏览器不支持‘kv-storage’? 此时此刻,这是非常有可能的。 幸运的是,这里有一个可用的 polyfill: https://github.com/GoogleChromeLabs/kv-storage-polyfill.

我建议您将其添加到您的应用程序中,如果您计划在这个阶段在生产中使用kv存储

进一步阅读

谷歌已经准备了一个演示文稿,你可能会发现有趣的阅读. 这里是URL: https://rollup-built-in-modules.glitch.me/

Published At
Categories with 技术
Tagged with
comments powered by Disqus