├── .gitignore
├── package.json
├── README.md
├── main.js
└── src
├── worker.js
├── virtual-list.html
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "worker",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "node main.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "koa": "^2.13.1",
14 | "koa-router": "^10.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 前端海量数据处理
2 |
3 | 针对前端处理海量数据,写了个人的解决方案!
4 |
5 | ## 虚拟列表
6 |
7 | [demo 文件](./src/virtual-list.html)
8 |
9 |
10 |
11 | ## 虚拟列表 + webWorker + indexDB 实现
12 |
13 |
14 |
15 | ### 启动步骤:
16 |
17 | 1. npm i
18 |
19 | 2. npm start
20 |
21 | 3. 访问 http://localhost:9527
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa')
2 | const Router = require('koa-router');
3 | const fs = require('fs/promises')
4 |
5 | const app = new Koa()
6 | const router = new Router()
7 |
8 | // 实现的虚拟列表
9 | router.get('/', async (ctx, next) => {
10 | const content = await fs.readFile('./src/index.html', { encoding: 'utf8' })
11 | ctx.body = content
12 | })
13 |
14 | // worker
15 | router.get('/worker.js', async (ctx, next) => {
16 | const content = await fs.readFile('./src/worker.js')
17 | ctx.body = content
18 | })
19 |
20 | const port = 9527
21 |
22 | app.use(router.routes()).use(router.allowedMethods()).listen(port)
23 |
24 | console.log(`预览:`, `\x1B[36mhttp://localhost:${port}\x1B[0m`)
25 |
--------------------------------------------------------------------------------
/src/worker.js:
--------------------------------------------------------------------------------
1 | const databaseName = 'virtualList'
2 | let db
3 | let isFinished = false
4 |
5 | const controlDatabase = db => {
6 | db.onversionchange = () => {
7 | postMessage({ type: 'close', msg: '只能打开一个页面哦,请关闭其他页面再刷新哦' })
8 | db.close()
9 | }
10 | }
11 |
12 | // 创建数据库
13 | const createDatabase = async () => {
14 | let version = 1
15 | const databases = await indexedDB.databases()
16 | const preDatabase = databases.find(({ name }) => name === databaseName)
17 | if (preDatabase) version = preDatabase.version + 1
18 |
19 | // indexedDB.deleteDatabase(databaseName)
20 | const database = indexedDB.open(databaseName, version)
21 | return new Promise((f, r) => {
22 | database.onsuccess = e => controlDatabase(e.target.result)
23 | database.onupgradeneeded = f
24 | database.onerror = r
25 | })
26 | }
27 |
28 | // 创建表
29 | const createTable = db => {
30 | return new Promise((f, r) => {
31 | try {
32 | db.deleteObjectStore('list')
33 | }catch (e) {
34 | console.log(e)
35 | }
36 | const table = db.createObjectStore('list', { keyPath: 'id' })
37 |
38 | table.transaction.oncomplete = () => {
39 | const store = db.transaction('list', 'readwrite').objectStore('list')
40 |
41 | let i = 0
42 | while (i < 100000) {
43 | store.add({ id: i++, num: Math.random() })
44 | }
45 |
46 | f(i)
47 | isFinished = true
48 | }
49 | })
50 | }
51 |
52 | // 检索
53 | const search = ({ size, start }) => {
54 | if (!isFinished) return []
55 |
56 | return new Promise((f, r) => {
57 | const store = db.transaction('list', 'readonly').objectStore('list')
58 | const range = IDBKeyRange.bound(start, start + size)
59 | const list = []
60 |
61 | store.openCursor(range).onsuccess = ({ target: { result } }) => {
62 | if (!result) {
63 | return f(list)
64 | }
65 |
66 | list.push(result.value)
67 | result.continue()
68 | }
69 | })
70 | }
71 |
72 | const start = async () => {
73 | const { target: { result } } = await createDatabase()
74 | const data = await createTable(db = result)
75 | postMessage({
76 | type: 'ok',
77 | data
78 | })
79 | }
80 |
81 | addEventListener('message', async ({ data }) => {
82 | const result = await search(data)
83 | postMessage(result)
84 | })
85 |
86 | start()
--------------------------------------------------------------------------------
/src/virtual-list.html:
--------------------------------------------------------------------------------
1 |
2 |