@ -14,7 +14,7 @@ export const Level = {
} ;
class VBase {
constructor ( scope , baseURL , login _page ) {
constructor ( scope , baseURL , login _page , users = { } ) {
if ( ! scope ) throw new Error ( 'VBase: scope is required' ) ;
if ( ! baseURL ) baseURL = window . location . origin ;
if ( baseURL === '' || baseURL === '/' ) baseURL = window . location . origin ;
@ -25,10 +25,16 @@ class VBase {
this . tokenKey = ` vbase_token ` ;
this . refreshTokenKey = ` vbase_refresh_token ` ;
this . userKey = ` vbase_user ` ;
this . users = users ;
this . _token = localStorage . getItem ( this . tokenKey ) || '' ;
this . _refreshToken = localStorage . getItem ( this . refreshTokenKey ) || '' ;
this . _user = JSON . parse ( localStorage . getItem ( this . userKey ) || 'null' ) ;
this . _pendingUserIDs = new Set ( ) ;
this . _loadingUserIDs = new Set ( ) ;
this . _resolvedUserIDs = new Set ( ) ;
this . _pendingUserFlush = null ;
this . _cachePublicUser ( this . _user ) ;
if ( this . _token ) {
this . fetchUser ( )
}
@ -56,6 +62,7 @@ class VBase {
this . _user = val ;
if ( val ) localStorage . setItem ( this . userKey , JSON . stringify ( val ) ) ;
else localStorage . removeItem ( this . userKey ) ;
this . _cachePublicUser ( val ) ;
}
// ========== API 请求 ==========
@ -212,6 +219,30 @@ class VBase {
this . token = '' ;
this . refreshToken = '' ;
this . user = null ;
for ( const id of Object . keys ( this . users ) ) {
delete this . users [ id ] ;
}
this . _pendingUserIDs . clear ( ) ;
this . _loadingUserIDs . clear ( ) ;
this . _resolvedUserIDs . clear ( ) ;
this . _pendingUserFlush = null ;
}
User ( id ) {
if ( ! id ) return { } ;
if ( ! this . users [ id ] ) {
this . users [ id ] = { } ;
}
if ( ! this . _resolvedUserIDs . has ( id ) && ! this . _loadingUserIDs . has ( id ) ) {
this . _pendingUserIDs . add ( id ) ;
if ( ! this . _pendingUserFlush ) {
this . _pendingUserFlush = Promise . resolve ( ) . then ( ( ) => this . _flushUserRequests ( ) ) ;
}
}
return this . users [ id ] ;
}
isExpired ( token ) {
@ -341,6 +372,57 @@ class VBase {
}
) ;
}
_cachePublicUser ( user ) {
if ( ! user ? . id ) return ;
const cached = {
... user ,
name : user . name || user . nickname || user . username || '' ,
icon : user . icon || user . avatar || '' ,
avatar : user . avatar || user . icon || '' ,
} ;
if ( ! this . users [ cached . id ] ) {
this . users [ cached . id ] = { } ;
}
Object . assign ( this . users [ cached . id ] , cached ) ;
this . _resolvedUserIDs . add ( cached . id ) ;
this . _loadingUserIDs . delete ( cached . id ) ;
}
async _flushUserRequests ( ) {
const ids = [ ... this . _pendingUserIDs ] . filter ( Boolean ) ;
this . _pendingUserIDs . clear ( ) ;
this . _pendingUserFlush = null ;
if ( ids . length === 0 ) return ;
for ( const id of ids ) {
this . _loadingUserIDs . add ( id ) ;
}
try {
const res = await this . request ( 'POST' , '/api/auth/users' , { ids } ) ;
const items = Array . isArray ( res ? . items ) ? res . items : [ ] ;
const found = new Set ( ) ;
for ( const item of items ) {
this . _cachePublicUser ( item ) ;
found . add ( item . id ) ;
}
for ( const id of ids ) {
this . _loadingUserIDs . delete ( id ) ;
if ( ! found . has ( id ) ) {
this . _resolvedUserIDs . add ( id ) ;
}
}
} catch ( error ) {
for ( const id of ids ) {
this . _loadingUserIDs . delete ( id ) ;
}
console . warn ( 'VBase: batch fetch users failed' , error ) ;
}
}
}
export default VBase ;