Javascript 如何实现异步锁或者是全局单例?
我想要通过 JS 实现全局单例的对象缓存,但似乎都没有很好的解决办法。
目前环境:node + vue 浏览器端运行
let cache = [];async function getUser(id){
return new Promise((resolve) => {
if(Object.prototype.hasOwnProperty.call(cache, id)){
return resolve(cache[id])
}
setTimeout(() => {
const obj = {
id:id,
name:Math.random() .toString(36)
}
cache[id] = obj
resolve(obj)
}, 200);
})
}
如,上面代码是通过ID获取一个用户对象,而这个用户对象本想缓存起来,反复利用。其中的setTimeout是表示从网络资源获取或者是从数据库获取都将会是异步操作反馈。
> getUser(1).then(data=>console.log(data))getUser(1).then(data=>console.log(data))
getUser(1).then(data=>console.log(data))
< Promise {<pending>}
VM323:1 {id: 1, name: "0.gayf057xhjo"}
VM323:2 {id: 1, name: "0.owi31fi79z"}
VM323:3 {id: 1, name: "0.3bya3r4poxn"}
如果连续执行多次,就会产生多个"用户对象", 通过名字鉴别,是因为缓存还未写入,导致后面的函数也会进入重新获取对象产生"新对象",前者先执行完毕写入的缓存对象也会被后来者覆盖,这是不被允许的。
如果之后再次获取,命中缓存了,获取到最后一次存储的缓存对象,前几次冗余的就会失效。
问题:
这个逻辑中,我想解决唯一缓存对象,或者是异步锁的实现,能够有效阻塞后来者,但不丢弃。
至于为什么要一起异步并发执行,而不逐个执行,是因为实际应用场景中,可能是有多个模块某个瞬间同时需要这块数据造成的。
希望各位大佬帮忙看看,提供思路方法。
回答:
getUser连续运行多次,因为同步的原因,没有走上面的if,都走了下面的定时器,2s后添加cache(此时才有的cache[id],在运行getUser才会走if里)并resolve,所以每一次都不一样。改的话可以这么改,cache中不存放具体数据,而是存放promise实例
let cache = {};async function getUser(id){
return cache[id] || (cache[id] = new Promise(resolve => {
setTimeout(() => {
const obj = {
id:id,
name:Math.random() .toString(36)
}
resolve(obj)
}, 200);
}))
}
getUser(1).then(data=>console.log(data))
getUser(1).then(data=>console.log(data))
getUser(1).then(data=>console.log(data))
回答:
https://github.com/ide/await-...
回答:
直接在cache[id]放个promise,检查这个promise的状态就知道要不要反复设置
以上是 Javascript 如何实现异步锁或者是全局单例? 的全部内容, 来源链接: utcz.com/p/935913.html