2016-12-11 3 views
1

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で何かですか?インスタンススタンピングのシナリオ。

セマフォが便利ですか? 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); 
      } 
     }); 
    }); 
} 

が、それは「一度」が、との約束のようなものになります

非同期スタイルでは、このようなものである可能性があります。

+0

この 'async'はあなたが参照しているものではありません、私は' stampede'メソッドを見つけることができませんか? – Bergi

+0

@Bergiは存在しません、私はスタンプのための非同期メソッドがどのようにできるか想像しようとしていました。私はその質問で、申し訳ありませんを明確にするつもりです! – Wiliam

答えて

1

約束のためにセマフォーや特別扱いは必要ありません。プロミスは非同期の結果を表す値であり、直接キャッシュすることができます。あなたは「何か」のようなものを望まないでしょうonceはちょうどonceです。あなたはもっと何も必要ありません。

それともidパラメータに基づいてそれらをキャッシュするため、実際に、あなたがアンダー/ 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 constructor antipatternを避けるようにしてください!

+0

私はこれをオンライナーに変換してあなたの気持ちを傷つけていないことを願っています:-) – Bergi

+0

はハハを傷つけませんでした!私は反パターンをチェックして、一度試してみるつもりです。実際にコードの最後の部分(ライブラリなし)は、 "作成"刻印権を妨げることはありませんか?作成では、ノードは同じIDのGoogleクラウドに複数回接続しようとしますが、作成する(または存在するかどうかを確認する)だけと残りのものを待ちます。 – Wiliam

+1

いいえ、 'this.storage [id]'は直ちに(結果ではなく約束で)満たされ、後続の呼び出しは単にそれを返し、 'create'をもう一度呼び出しません。 – Bergi

関連する問題