当我在 NodeJS 中使用 Google Cloud 服务时,我必须访问存储桶(在存储中)等资源,并且第一次调用它们时,我必须检查它们是否存在,如果不存在,则创建它们。
好吧,如果多个资源在应用程序启动时访问同一个存储桶,它们将尝试同时创建它。
为了防止踩踏,我必须使用这样的东西:
getStorage(id) {
return new Promise((resolve, reject) => {
// Exists storage?
if(id in this.storage) {
let storage = this.storage[id];
// Storage is ready, deliver
if(storage.ready) {
return resolve(storage);
}
// Not ready, wait until storage is ready
let wait;
let start = +Date.now();
wait = setInterval(() => {
// Storage is now ready
if(storage.ready) {
clearInterval(wait);
return resolve(storage);
}
// Timeout in 15 seconds
if(+Date.now() - start > 15*1000) {
clearInterval(wait);
return reject(new Error('timeout while waiting storage creation'));
}
}, 10);
return;
}
// Start storage creation
let storage = new Storage(id);
this.storage[id] = storage;
storage
.create()
.then(resolve, reject);
});
}
lodash、下划线或异步中是否有任何内容可以帮助解决这种情况?实例踩踏场景。
信号量会有用吗?
在异步风格中,它可能是这样的:
getStorage(id) {
return new Promise((resolve, reject) => {
// already found
if(id in this.storage) {
resolve(this.storage[id]);
return;
}
// prevent stampede
// async.stampede( UNIQUE_ID, CREATE, RESULT )
// - CREATE will be called once for UNIQUE_ID
async.stampede(id, (end) => {
let storage = new Storage(id);
storage
.create()
.then(
() => end(null, storage),
(err) => end(err)
);
}, (err, result) => {
if(err) reject(err);
else {
this.storage[id] = storage;
resolve(result);
}
});
});
}
在 lodash 中,它可以是类似“一次”的东西,但带有 promise 。
最佳答案
您不需要任何信号量或对 promise 进行特殊处理。 Promise 是表示异步结果的值,您可以直接缓存它们。您不需要“类似”一次
,您想要完全一次
。您不再需要任何东西。
或者实际上,由于您想根据 id
参数缓存它们,因此您需要使用 memoize
来自 Underscore/Lodash:
getStorage: _.memoize(id => new Storage(id).create())
或者在没有库的情况下编写,
getStorage(id) {
// Exists storage?
if (id in this.storage) {
return this.storage[id]; // it's a promise
} else {
// Start storage creation
let storage = new Storage(id);
let promise = storage.create();
this.storage[id] = promise; // store the promise!
return promise;
}
}
关于javascript - 在nodejs中实例化对象时防止踩踏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41085713/