尝试缓存某些内容时处理 Promise

问题描述 投票:0回答:2

我有一个第三方Angular库作为依赖项,它正在执行http请求(超级代理),所以我无法拦截它。我想缓存我获得的值,因为我在 UI 中有一个有时包含类似信息的列表,并且我不需要总是发出相同的请求。

这是我从 API 接收用户的代码:

getUser(userId: number): Promise<any> {
    return new Promise(async (resolve) => {
      const cached = this.cacheService.get(userId);
        if (cached) {
          resolve(cached);
        } else {
        let user = await this.THIRDPARTYAPI.getUser(userId);
        this.cacheService.put(user.id, user);
        resolve(user);
      }
  });}

(异步/等待只是我最近的尝试)。

这将在以下部分中使用

     data.forEach((row: any) => {
       this.getUser(row.userId).then((user: any)=>{
      //do something
      });

但是,它总是会触发 THIRDPARTYAPI.getUser(userId) 方法,因此它会将值放入我的缓存服务中,在已经很晚并且值已经被检查之后。它并没有真正一个接一个地完全运行 forEach,我很困惑,我怎么能意识到这一点。

javascript html angular async-await promise
2个回答
0
投票

问题似乎并不在于

getUser()
方法,而在于你如何在
forEach()
中使用它。

我认为您尝试缓存每个

userId
的响应的原因是因为它们在
data
中多次出现。

如果您在

getUser()
中调用
forEach()
,您应该记住,每次迭代都不会等到完成。这意味着对于 data
 中的每一项,您都会立即调用 
getUser()
。由于这个方法调用得太快,你的 
cacheService
 总是会错过。


解决此问题的一种方法可能是在

await

 块内使用 
for...of
,如下所示:

for (const row of data) { const result = await this.getUser(row.userId) // do something with result }
这将按顺序执行每个请求。


另一种方法可能是根据

row.userId

 属性过滤唯一行,对它们调用 
getUser()
,然后执行 
forEach()
 循环。此时,所有用户对象都应该已被缓存,您的 
forEach()
 将始终命中缓存。


0
投票
以下是如何缓存 Promise 的示例:

getUser(userId: number): Promise<any> { const cached = this.cacheService.get(userId); if (cached) return cached; const userPromise = this.THIRDPARTYAPI.getUser(userId); this.cacheService.put(user.id, userPromise); // Optional if you want the cache to eventually contain users and not just promises. userPromise.then(user => cacheService.put(user.id, user)); return userPromise; }
顺便说一句,您的原始代码对 

new Promise()

 的使用非常糟糕,它会忽略错误。这就是您的原始代码应该是什么样子,以供您将来参考:

async getUser(userId: number): Promise<any> { const cached = this.cacheService.get(userId); if (cached) return cached; const user = await this.THIRDPARTYAPI.getUser(userId); this.cacheService.put(user.id, user); return user; }
在大多数情况下,

new Promise()

是一个危险信号,表明不好的事情即将发生。

© www.soinside.com 2019 - 2024. All rights reserved.