好久之前写的chrome拓展我竟然自己一直在用, 常用的功能是字典, todo列表, 收集tab和笔记本. 用了那么久问题也出了不少, 今天在删笔记本和添加todo的时候出了大bug, 那么就来看看除了什么问题.

问题

我在向todolist添加一条todo的时候报错了.

1
QUOTA_BYTES_PER_ITEM

咋肥ser? 到文档里看了下, 原来是chrome拓展对storage的大小有限制, 分别对总大小/单条数据大小/数据条数/每小时操作次数/每分钟操作次数有限制. 这个错误是超过了单条数据大小.

由于一开始对这些限制没有了解加入考虑, 我这个应用的数据结构存在问题并且已经定了. 我的todolist现在有80条左右, 那么限制80条todo一定是不合理的, 于是需要想一个办法.

解决

经过了一番粗糙的思考, 我决定分批保存, 思路非常简单: 在设置变量的时候判断item大小并分成n个, 在n大于1的时候在原本的键上加后缀, 取出的时候根据后缀规律拼接成一个item.

幸好之前对storage进行了封装, 在这里改起来就非常方便, 并且所有使用storage的地方都可以应用这次修改.

代码在非常简单, 就简单地贴一下, 可以点近左侧连接仔细看.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
set(key, value) {
let batches = getBatch(key, value)
let processes = []
batches.forEach((item, index) => {
let obj = {}
obj[index === 0 ? key : `${key}-p${index + 1}`] = item
processes.push(new Promise((resolve, reject) => {
chrome.storage.sync.set(obj, (callback) => {
catchError(reject)
resolve(`ok${callback}`);
})
}))
})
return Promise.all(processes)
.then(res => merge(res), reject => Promise.reject(reject))
},
get(key) {
let getFromStorage = function (originKey, level = 1) {
let _key = level === 1 ? originKey : `${key}-p${level}`
return new Promise((resolve) => {
chrome.storage.sync.get(_key, (callback) => {
resolve(callback[_key])
})
})
}
return (async function () {
let level = 1, keepGoing = true, cache = []
while (keepGoing) {
let temp = await getFromStorage(key, level++)
if (!temp) {
keepGoing = false
} else {
cache.push(temp)
}
}
if (cache.length) {
return merge(cache)
} else {
return Promise.reject(`get ${key} failed`)
}
})()
}