简体   繁体   中英

While loop within .then() of a promise

I am trying to do some logic where it will edit the length of minheap.heapList . I am pretty new to Promises so I am not sure how to approach this. Within the while loop I will be calling some async function as well. Not quite sure how to properly handle the race conditions

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

The goal of this is to try to convert my synchronous code into asynchronous. .pop() from my synchronous code will be replaced with .popAsync() to return a promise .

Here is the synchronous logic:

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

In order to return an array of promises to the Promise.all , you need to return in the 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;
}))

Your question is a bit unclear, but you could do this:

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

Note that your processNode function can itself be asynchronous.

Also note that if you do it this way, the values of source are not going to be assigned in a deterministic order.

Edit:

The answer here suggested an improvement in my answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM