forked from newthuhole/hole_thu_frontend
add comment cache
This commit is contained in:
20
src/Flows.js
20
src/Flows.js
@@ -30,13 +30,17 @@ function load_single_meta(show_sidebar,token,parents) {
|
||||
正在加载 #{pid}
|
||||
</div>
|
||||
);
|
||||
Promise.all([
|
||||
API.get_single(pid,token),
|
||||
API.load_replies(pid,token,color_picker),
|
||||
])
|
||||
.then((res)=>{
|
||||
const [single,replies]=res;
|
||||
API.get_single(pid,token)
|
||||
.then((single)=>{
|
||||
single.data.variant={};
|
||||
return new Promise((resolve,reject)=>{
|
||||
API.load_replies_with_cache(pid,token,color_picker,parseInt(single.data.reply))
|
||||
.then((replies)=>{resolve([single,replies])})
|
||||
.catch(reject);
|
||||
});
|
||||
})
|
||||
.then((res)=>{
|
||||
let [single,replies]=res;
|
||||
show_sidebar(
|
||||
title_elem,
|
||||
<FlowSidebar
|
||||
@@ -212,7 +216,7 @@ class FlowSidebar extends PureComponent {
|
||||
loading_status: 'loading',
|
||||
error_msg: null,
|
||||
});
|
||||
API.load_replies(this.state.info.pid,this.props.token,this.color_picker)
|
||||
API.load_replies(this.state.info.pid,this.props.token,this.color_picker,null)
|
||||
.then((json)=>{
|
||||
this.setState((prev,props)=>({
|
||||
replies: json.data,
|
||||
@@ -401,7 +405,7 @@ class FlowItemRow extends PureComponent {
|
||||
this.setState({
|
||||
reply_status: 'loading',
|
||||
});
|
||||
API.load_replies(this.state.info.pid,this.props.token,this.color_picker)
|
||||
API.load_replies_with_cache(this.state.info.pid,this.props.token,this.color_picker,parseInt(this.state.info.reply))
|
||||
.then((json)=>{
|
||||
this.setState((prev,props)=>({
|
||||
replies: json.data,
|
||||
|
||||
98
src/cache.js
Normal file
98
src/cache.js
Normal file
@@ -0,0 +1,98 @@
|
||||
const CACHE_DB_VER=1;
|
||||
const MAINTENANCE_STEP=500;
|
||||
const MAINTENANCE_COUNT=5000;
|
||||
|
||||
class Cache {
|
||||
constructor() {
|
||||
this.db=null;
|
||||
this.added_items_since_maintenance=0;
|
||||
const open_req=indexedDB.open('hole_cache_db',CACHE_DB_VER);
|
||||
open_req.onerror=console.error.bind(console);
|
||||
open_req.onupgradeneeded=(event)=>{
|
||||
console.log('comment cache db upgrade');
|
||||
const db=event.target.result;
|
||||
const store=db.createObjectStore('comment',{
|
||||
keyPath: 'pid',
|
||||
});
|
||||
store.createIndex('last_access','last_access',{unique: false});
|
||||
};
|
||||
open_req.onsuccess=(event)=>{
|
||||
console.log('comment cache db loaded');
|
||||
this.db=event.target.result;
|
||||
setTimeout(this.maintenance.bind(this),1);
|
||||
};
|
||||
}
|
||||
|
||||
get(pid,target_version) {
|
||||
return new Promise((resolve,reject)=>{
|
||||
if(!this.db)
|
||||
return resolve(null);
|
||||
const tx=this.db.transaction(['comment'],'readwrite');
|
||||
const store=tx.objectStore('comment');
|
||||
const get_req=store.get(pid);
|
||||
get_req.onsuccess=()=>{
|
||||
let res=get_req.result;
|
||||
if(!res) {
|
||||
console.log('cache miss');
|
||||
resolve(null);
|
||||
} else if(target_version===res.version) { // hit
|
||||
console.log('cache hit');
|
||||
res.last_access=+new Date();
|
||||
store.put(res);
|
||||
resolve(res.data);
|
||||
} else { // expired
|
||||
console.log('cache expired: ver',res.version,'target',target_version);
|
||||
store.delete(pid);
|
||||
resolve(null);
|
||||
}
|
||||
};
|
||||
get_req.onerror=reject;
|
||||
});
|
||||
}
|
||||
|
||||
put(pid,target_version,data) {
|
||||
return new Promise((resolve,reject)=>{
|
||||
if(!this.db)
|
||||
return resolve();
|
||||
const tx=this.db.transaction(['comment'],'readwrite');
|
||||
const store=tx.objectStore('comment');
|
||||
store.put({
|
||||
pid: pid,
|
||||
version: target_version,
|
||||
data: data,
|
||||
last_access: +new Date(),
|
||||
});
|
||||
if(++this.added_items_since_maintenance===MAINTENANCE_STEP)
|
||||
setTimeout(this.maintenance.bind(this),1);
|
||||
});
|
||||
}
|
||||
|
||||
maintenance() {
|
||||
if(!this.db)
|
||||
return;
|
||||
const tx=this.db.transaction(['comment'],'readwrite');
|
||||
const store=tx.objectStore('comment');
|
||||
let count_req=store.count();
|
||||
count_req.onsuccess=()=>{
|
||||
let count=count_req.result;
|
||||
if(count>MAINTENANCE_COUNT) {
|
||||
console.log('comment cache db maintenance',count);
|
||||
store.index('last_access').openKeyCursor().onsuccess=(e)=>{
|
||||
let cur=e.target.result;
|
||||
if(cur) {
|
||||
console.log('maintenance: delete',cur);
|
||||
store.delete(cur.primaryKey);
|
||||
if(--count>MAINTENANCE_COUNT)
|
||||
cur.continue();
|
||||
}
|
||||
};
|
||||
} else {
|
||||
console.log('comment cache db not full',count);
|
||||
}
|
||||
this.added_items_since_maintenance=0;
|
||||
};
|
||||
count_req.onerror=console.error.bind(console);
|
||||
}
|
||||
};
|
||||
|
||||
export let cache=new Cache();
|
||||
@@ -1,6 +1,7 @@
|
||||
import {get_json} from './infrastructure/functions';
|
||||
import {PKUHELPER_ROOT} from './infrastructure/const';
|
||||
import {API_BASE} from './Common';
|
||||
import {cache} from './cache';
|
||||
|
||||
export const API_VERSION_PARAM='&PKUHelperAPI=3.0';
|
||||
export {PKUHELPER_ROOT};
|
||||
@@ -12,7 +13,8 @@ function token_param(token) {
|
||||
export {get_json};
|
||||
|
||||
export const API={
|
||||
load_replies: (pid,token,color_picker)=>{
|
||||
load_replies: (pid,token,color_picker,cache_version)=>{
|
||||
pid=parseInt(pid);
|
||||
return fetch(
|
||||
API_BASE+'/api.php?action=getcomment'+
|
||||
'&pid='+pid+
|
||||
@@ -25,6 +27,9 @@ export const API={
|
||||
else throw new Error(JSON.stringify(json));
|
||||
}
|
||||
|
||||
cache.put(pid,cache_version,json);
|
||||
|
||||
// also change load_replies_with_cache!
|
||||
json.data=json.data
|
||||
.sort((a,b)=>{
|
||||
return parseInt(a.timestamp,10)-parseInt(b.timestamp,10);
|
||||
@@ -39,6 +44,29 @@ export const API={
|
||||
});
|
||||
},
|
||||
|
||||
load_replies_with_cache: (pid,token,color_picker,cache_version)=> {
|
||||
pid=parseInt(pid);
|
||||
return cache.get(pid,cache_version)
|
||||
.then((json)=>{
|
||||
if(json) {
|
||||
// also change load_replies!
|
||||
json.data=json.data
|
||||
.sort((a,b)=>{
|
||||
return parseInt(a.timestamp,10)-parseInt(b.timestamp,10);
|
||||
})
|
||||
.map((info)=>{
|
||||
info._display_color=color_picker.get(info.name);
|
||||
info.variant={};
|
||||
return info;
|
||||
});
|
||||
|
||||
return json;
|
||||
}
|
||||
else
|
||||
return API.load_replies(pid,token,color_picker,cache_version);
|
||||
});
|
||||
},
|
||||
|
||||
set_attention: (pid,attention,token)=>{
|
||||
let data=new URLSearchParams();
|
||||
data.append('user_token',token);
|
||||
|
||||
Reference in New Issue
Block a user