在nodejs中实例化对象时防止踩踏
当我在NodeJS中使用Google Cloud服务时,我必须访问“存储”(如存储)中的资源,并且在我第一次给他们打电话时,我必须检查它们是否存在,如果不存在,请创build它们。
那么,如果多个资源在应用程序启动时访问同一个存储桶,他们将尝试同时创build它。
为了防止踩踏,我必须使用这样的东西:
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,下划线或asynchronous,有助于这种情况? 一个实例踩踏场景。
信号灯会有用吗?
在asynchronous风格,它可能是这样的:
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是表示asynchronous结果的值,您可以直接caching它们。 你不需要once
“喜欢”,你只需要once
。 你不需要更多。
或者实际上,因为你想要基于id
参数来caching它们,你需要使用Underscore / Lodash中的memoize
:
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; } }
确保避免Promise
构造函数反模式 !