我有一个第三方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,我很困惑,我怎么能意识到这一点。
问题似乎并不在于
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()
将始终命中缓存。
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()
是一个危险信号,表明不好的事情即将发生。