Typescript类变量未更新/保留值

时间:2019-12-23 03:30:26

标签: javascript typescript react-native

我正在尝试创建一个类,该类将从Firestore数据库中获取/缓存用户。由于某些原因,我似乎无法保存或公开先前创建的诺言。这是我的课程:

export class UserCache {
  private cacheTimeMilliseconds: number = 600000;
  private userCache: any = {};

  public getCacheUser(userid: string): Promise<User> {
    return new Promise((resolve, reject) => {
      let d = new Date();
      d.setTime(d.getTime() - this.cacheTimeMilliseconds);
      if (this.userCache[userid] && this.userCache[userid].complete && this.userCache[userid].lastAccess > d.getTime()) {
        console.log("User cached");
        resolve(this.userCache[userid].user);
      }

      console.log("Need to cache user");
      this.userCache[userid] = {
        complete: false
      };
      this.getSetUserFetchPromise(userid).then((data) => {
        let user: User = <User>{ id: data.id, ...data.data() };
        this.userCache[userid].user = user;
        this.userCache[userid].complete = true;
        this.userCache[userid].lastAccess = Date.now();
        resolve(user);
      });
    });
  }

  private getSetUserFetchPromise(userid: string): Promise<any> {
    console.log(this.userCache[userid]);
    if (this.userCache[userid] && this.userCache[userid].promise) {
      return this.userCache[userid].promise;
    } else {
      console.log("Creating new user fetch request.");
      this.userCache[userid].promise = firestore().collection('users').doc(userid).get();
      console.log(this.userCache[userid]);
      return this.userCache[userid].promise;
    }
  }
}

日志:(只有2个唯一用户,因此只能创建2个新请求)

enter image description here

在日志中,我可以看到在getSetUserFetchPromise中设置了promise,但是下次调用该函数时,不再设置该属性。我怀疑这是范围问题或并发问题,但我似乎无法解决。

我正在使用getCacheUserlet oCache = new UserCache()的消费类中呼叫oCache.getCacheUser('USERID')

按照以下Tuan的答案进行编辑

UserCacheProvider.ts

import firestore from '@react-native-firebase/firestore';
import { User } from '../static/models';

class UserCache {
  private cacheTimeMilliseconds: number = 600000;
  private userCache: any = {};

  public getCacheUser(userid: string): Promise<User> {
    return new Promise((resolve, reject) => {
      let d = new Date();
      d.setTime(d.getTime() - this.cacheTimeMilliseconds);
      if (this.userCache[userid] && this.userCache[userid].complete && this.userCache[userid].lastAccess > d.getTime()) {
        console.log("User cached");
        resolve(this.userCache[userid].user);
      }

      console.log("Need to cache user");
      this.userCache[userid] = {
        complete: false
      };
      this.getSetUserFetchPromise(userid).then((data) => {
        let user: User = <User>{ id: data.id, ...data.data() };
        this.userCache[userid].user = user;
        this.userCache[userid].complete = true;
        this.userCache[userid].lastAccess = Date.now();
        resolve(user);
      });
    });
  }

  private getSetUserFetchPromise(userid: string): Promise<any> {
    console.log(this.userCache[userid]);
    if (this.userCache[userid] && this.userCache[userid].promise) {
      return this.userCache[userid].promise;
    } else {
      console.log("Creating new user fetch request.");
      this.userCache[userid].promise = firestore().collection('users').doc(userid).get();
      console.log(this.userCache[userid]);
      return this.userCache[userid].promise;
    }
  }
}

const userCache = new UserCache();
export default userCache;

ChatProvider.ts(用法)

let promises = [];

          docs.forEach(doc => {
            let message: Message = <Message>{ id: doc.id, ...doc.data() };

            promises.push(UserCacheProvider.getCacheUser(message.senderid).then((oUser) => {
              let conv: GCMessage = {
                _id: message.id,
                text: message.messagecontent,
                createdAt: new Date(message.messagedate),
                user: <GCUser>{ _id: oUser.id, avatar: oUser.thumbnail, name: oUser.displayname }
              }

              if (message.type && message.type == 'info') {
                conv.system = true;
              }

              if (message.messageattachment && message.messageattachment != '') {
                conv.image = message.messageattachment;
              }

              return conv;
            }));
          });

          Promise.all(promises).then((values) => {
            resolve(values);
          });

2 个答案:

答案 0 :(得分:0)

当前,每次访问缓存用户时,您都会创建一个新的UserCache。您必须导出UserCache类的实例,因此您的应用仅使用单个实例。

UserCache.ts

class UserCache {
}

const userCache = new UserCache();
export default userCache;

SomeFile.ts

import UserCache from './UserCache';

UserCache.getCacheUser('USERID')

更新

添加了一些测试

class UserCache {
  userCache = {};

  getUser(id) {
    return new Promise((resolve, reject) => {
      if (this.userCache[id]) {
        resolve({
          ...this.userCache[id],
          isCache: true,
        });
      }
      this.requestUser(id).then(data => {
        resolve(data);
        this.userCache[id] = data;
      });
    });
  }

  requestUser(id) {
    return Promise.resolve({
      id,
    });
  }
}

const userCache = new UserCache();
export default userCache;

userCache.test.ts

import UserCache from '../test';

describe('Test user cache', () => {
  test('User cached successfully', async () => {
    const user1: any = await UserCache.getUser('test1');
    expect(user1.isCache).toBeUndefined();
    const user2: any = await UserCache.getUser('test1');
    expect(user2.isCache).toBe(true);
  });
});

doc

答案 1 :(得分:0)

没有看到调用代码,可能是getCacheUser在Firestore解析之前被调用了两次。

顺便说一句,我认为重构类可以使调试更容易。我想知道为什么它会缓存用户,承诺完成状态以及承诺本身。为什么不只是缓存承诺,就像这样:

interface UserCacheRecord {
    promise: Promise<User>
    lastAccess: number
}

export class UserCache {
    private cacheTimeMilliseconds: number = 600000;
    private userCache: { [userid: string]: UserCacheRecord } = {};

    public async getCacheUser(userid: string): Promise<User> {
        let d = new Date();
        const cacheExpireTime = d.getTime() - this.cacheTimeMilliseconds

        if (this.userCache[userid] && this.userCache[userid].lastAccess > cacheExpireTime) {
            console.log("User cached");
            return this.userCache[userid].promise
        }

        console.log("Need to cache user");

        this.userCache[userid] = {
            promise: this.getUser(userid),
            lastAccess: Date.now()
        }

        return this.userCache[userid].promise
    }

    private async getUser(userid: string): Promise<User> {
        const data = firestore().collection('users').doc(userid).get();
        return <User>{ id: data.id, ...data.data() };
    }
}