Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cache promise #1

Open
simplefeel opened this issue Jan 18, 2021 · 0 comments
Open

cache promise #1

simplefeel opened this issue Jan 18, 2021 · 0 comments

Comments

@simplefeel
Copy link
Owner

simplefeel commented Jan 18, 2021

cache promise

有如下代码

const usersCache = new Map<string, User>();

const getUserById = async (userId: string): Promise<User> => {
  if (!usersCache.has(userId)) {
    const user = await request.get(`https://users-service/${userId}`);
    usersCache.set(userId, user);
  }

  return usersCache.get(userId);
};

这段代码用来获取用户的信息,但是加入了缓存处理,如果缓存有值的话直接从缓存获取,不用再去调用接口获取,对于提升代码性能,提高响应速度很有帮助。但是也有另外一个问题,比如我重复调用这个方法

await Promise.all([
  getUserById('user1'),
  getUserById('user1')
]);

这样使用,还是会调用两次接口,缓存无法命中,原因是我们缓存的是一个异步请求的响应值,当连续调用这个方法时,上一个异步请求的结果还没响应,下一个异步请求就发出去了。那该怎么解决呢?可以通过缓存Promise的方式进行解决,代码如下

const userPromisesCache = new Map<string, Promise<User>>();

const getUserById = (userId: string): Promise<User> => {
  if (!userPromisesCache.has(userId)) {
    const userPromise = request.get(`https://users-service/v1/${userId}`);
    userPromisesCache.set(userId, userPromise);
  }

  return userPromisesCache.get(userId)!;
};

我们不再是缓存异步请求的响应结果,而是直接缓存这个异步请求返回的Promise,这样处理的好处是我们不用再等待请求响应成功,当连续连续getUserById时,可以立即返回上一个已经缓存的promise,从而实现最终发送一个http请求。但这样处理还有点缺陷,就是如果上一个promise``reject了,就会导致后面的调用始终是reject,我们需要修改一下,将reject``promise从缓存中去掉,代码修改如下

const getUserById = (userId: string): Promise<User> => {
  if (!userPromisesCache.has(userId)) {
    const userPromise = request.get(`https://users-service/v1/${userId}`);
    userPromisesCache.set(userId, userPromise);
  }

  const cachePromise = userPromisesCache.get(userId)!;

  cachePromise.catch((err)=>{
    userPromisesCache.delete(userId)
  })

  return cachePromise
};

github上也有专门处理缓存相关的库,例如Memoizee,针对上述场景修改代码如下

import memoize from 'memoizee';

const getUserById = memoize(async (userId: string): Promise<User> => {
  const user = await request.get(`https://users-service/${userId}`);
  return user;
}, { promise: true});

除了缓存promise,日常工作中,对于处理比较慢的操作,例如请求、耗时长的数据处理等我们应该充分利于缓存来提升二次处理的效率。

@simplefeel simplefeel changed the title 优化异步编程代码的一些技巧 编写异步编程代码的一些技巧 Jan 18, 2021
@simplefeel simplefeel changed the title 编写异步编程代码的一些技巧 缓存Promise和并发await Jan 18, 2021
@simplefeel simplefeel changed the title 缓存Promise和并发await 缓存Promise Feb 25, 2021
@simplefeel simplefeel changed the title 缓存Promise cache promise Mar 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant