2017-01-28 17 views
0

私はminheap.heapListの長さを編集するいくつかのロジックをしようとしています。私はかなりPromisesに新しいですので、私はこれにどのようにアプローチするか分かりません。 while loopの中で私はasyncの機能も同様に呼び出す予定です。競合状態を適切に処理する方法が不明確約束の.then()内にループwhile

let minheap = new MinHeap(); 
    let i = 0; 
    Promise.all(logSources.map(logSource => { 
     logSource.popAsync().then(log => { 
      minheap.insert({ 
       ts: log.date.getTime(), 
       source: i++, 
       data: log 
      }) 
     }); 
     i += 1; 
    })).then(
     while(minheap.heapList.length) { 
      ... 
      // async logic 
      ... 
     } 
    ); 

これは、同期コードを非同期に変換しようとすることです。同期コードの.pop().popAsync()に置き換えてpromiseを返します。ここで

が同期ロジックです:

const lenLogSources = logSources.length; 
let minheap = new MinHeap(); 
for (let i = 0; i < lenLogSources; i++) { 
    let log = logSources[i].pop(); 
    minheap.insert({ 
     ts: log.date.getTime(), 
     source: i, 
     data: log 
    }) 
} 
while (minheap.heapList.length) { 
    let heapNode = minheap.popMin(); 
    let currTimestamp = heapNode['ts']; 
    printer.print(heapNode.data); 
    let nextMinTimestamp = minheap.getPeakTimestamp(); 
    while (currTimestamp <= nextMinTimestamp) { 
     let log = logSources[heapNode['source']].pop(); 
     if (log) { 
      let logtime = log.date.getTime(); 
      if (logtime <= nextMinTimestamp) { 
       printer.print(log); 
       currTimestamp = logtime; 
      } else { 
       minheap.insert({ 
        ts: logtime, 
        source: heapNode["source"], 
        data: log 
       }); 
       break; 
      } 
     } else { 
      heapNode = minheap.popMin(); 
      printer.print(heapNode.data); 
      currTimestamp = heapNode['ts']; 
      if (minheap.heapList.length) { 
       nextMinTimestamp = minheap.getPeakTimestamp(); 
      } else { 
       while (true) { 
        let m = logSources[heapNode['source']].pop(); 
        if (m) { 
         printer.print(m); 
        } else { 
         console.log('Drained: ' + heapNode['source']); 
         break; 
        } 
       } 
       break; 
      } 
     } 
    } 
} 
+0

a)コールバックを 'then'に渡す必要があります。ループ構造ではありません。b)非同期ロジックの周りに' while'ループを使用することはできません。代わりに再帰的なアプローチを使用してください。 – Bergi

答えて

2

Promise.allに約束の配列を返すために、あなたはmapreturnする必要があります。

Promise.all(logSources.map(logSource => { 
    const logSourcePromise = logSource.popAsync().then(log => { 
     minheap.insert({ 
      ts: log.date.getTime(), 
      source: i++, 
      data: log 
     }) 
    }); 
    i += 1; 
    return logSourcePromise; 
})) 
2

あなたの質問は少し不明ですこれを行うことができます:

Promise 
    .all(
    logSources.map(
     logSource => 
     logSource 
      .popAsync() 
      .then(log => 
      minheap.insert({ 
       ts: log.date.getTime(), 
       source: minheap.heapList.length, 
       data: log 
      })) 
    ) 
) 
    .then(
    () => { 
     const fcn =() => 
     (minheap.heapList.length) 
     ? minheap 
      .popMinAsync() 
      .then(processNode) 
      .then(v => results.push(v)) 
      .then(fcn); 
     : Promise.resolve(); 
     fcn(); 
    }) 
); 

processNode関数自体が非同期であることに注意してください。

このようにすれば、sourceの値は確定的な順序で割り当てられないことにも注意してください。

編集:

答えhereは、私の答えの改善を示唆しました。

+0

は、このアプローチでスタック領域が不足する可能性がありますか? 'logSources'の数が多い場合は? – Liondancer

+2

@Liondancer - まず:クールなユーザー名。第二に、私はこれを再帰的に知っているが、そうではない。 'fcn()'はそれ自身ではなく、非同期コールバックによって呼び出されます。実際のスタックは成長しませんが、スタックのようなリンクされたクロージャのリストがヒープ内に作成されます。 – Malvolio

+0

まだまだ= [あなたはどうぞご覧ください。 http://dpaste.com/3ZDGAAZあなたが提案したパターンに従おうとしています。現在、 'fail'という無限の出力を得ています。 – Liondancer