while循环在.then()中

时间:2017-01-28 09:49:26

标签: javascript node.js promise

我正在尝试做一些逻辑,它会编辑minheap.heapList的长度。我对Promises很新,所以我不知道如何处理这个问题。在while loop内,我也会调用一些async函数。不太确定如何正确处理竞争条件

    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;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:2)

为了向Promise.all返回一系列承诺,您需要return中的map

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;
}))

答案 1 :(得分: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表明我的答案有所改善。