模型本地存储
更新时间: 2021-06-08 16:45:21
还是之前那个模型查看的问题,有个模型50M,每次打开都需要从服务器上请求模型,速度太慢被老板吐槽了,所以考虑将模型存在本地,具体的方案呢,我选定了使用IndexedDB
我的思路是这样的:
- 首先在
indexedDB
查找有没有这个模型的数据存在 - 如果存在就将这个数据查询出来,加载本地的模型
- 如果不存在就从服务器请求模型数据,然后存在本地
indexedDB
但是有两个问题:
- 从服务器请求到的模型怎么转换成
blob
存进indexedDB
threejs
的gltfLoader
需要提供的是一个确切的url
地址
开始解决问题:
- 首先解决怎么把从服务器请求到的模型转换成
blob
axios({
url:url,
method: 'get',
responseType:"blob"
}).then(res =>{
let blob = res.data;
})
1
2
3
4
5
6
7
2
3
4
5
6
7
然后我们把这个数据存进IndexedDB
:
let id = "xxxxx" //这里随便弄的一个id
let indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
if(!indexedDB){
console.log("不支持indexedDB")
}
let request = indexedDB.open('userModels');
let db
request.onupgradeneeded = (event) =>{
console.log("数据库更新")
db = event.target.result;
// 判断是否有这个表
if (!db.objectStoreNames.contains('models')) {
// 创建表
let objectStore;
//使用id作为主键
objectStore = db.createObjectStore('models', {
// 主键
keyPath: 'id'
});
}
}
request.onsuccess = (event) =>{
//数据库打开成功
db = event.target.result
let transaction = db.transaction(['models'], 'readwrite');
let objStore = transaction.objectStore('models');
let req = objStore.get(id);
req.onsuccess = (e) => {
if (req.result) {
//拿到数据
console.log(req.result)
} else {
//未查询到数据
axios({
url:url,
method: 'get',
responseType:"blob"
}).then(res =>{
//将模型输入存进数据库
let blob = res.data;
db.transaction(['models'], 'readwrite').objectStore('models').add({id:id,blob:blob})
})
}
}
};
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
43
44
45
46
47
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
43
44
45
46
47
- 第二个问题,
blob
怎么转换成url
URL.createObjectURL()
静态方法会创建一个 DOMString
,其中包含一个表示参数中给出的对象的URL
。这个 URL
的生命周期和创建它的窗口中的 document
绑定。这个新的URL
对象表示指定的 File
对象或 Blob
对象。
objectURL = URL.createObjectURL(object);
1
其中参数object是: 用于创建 URL
的 File
对象、Blob
对象或者 MediaSource
对象。
# 最终代码
解决了两个问题后,我们来写一个获取模型url的方法:
function getRealUrl(id,url){
return new Promise((resolve,reject) => {
let fileType = url.split('.')[url.split('.').length - 1]
//查找数据库里有没有
let indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB;
if(!indexedDB){
resolve(url)
return false
}
let request = indexedDB.open('userModels');
let db
request.onupgradeneeded = (event) =>{
console.log("数据库更新")
db = event.target.result;
// 判断是否有这个表
if (!db.objectStoreNames.contains('models')) {
// 创建表
let objectStore;
objectStore = db.createObjectStore('models', {
// 主键
keyPath: 'id'
});
}
}
request.onsuccess = (event) =>{
console.log("数据库打开成功")
db = event.target.result
let transaction = db.transaction(['models'], 'readwrite');
let objStore = transaction.objectStore('models');
let req = objStore.get(id);
req.onsuccess = (e) => {
if (req.result) {
console.log('已经查询到数据为:');
console.log(req.result);
let modelUrl = URL.createObjectURL(req.result.blob)
db.close();
resolve(modelUrl)
} else {
console.log('未查询到数据');
axios({
url:url,
method: 'get',
responseType:"blob"
}).then(res =>{
let blob = res.data;
db.transaction(['models'], 'readwrite').objectStore('models').add({id:id,blob:blob})
let modelUrl = URL.createObjectURL(blob)
db.close();
resolve(modelUrl)
}).catch(() =>{
db.close();
resolve(url)
})
}
}
};
})
}
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58