在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构造函数反模式 !