summaryrefslogtreecommitdiff
path: root/lib/internal/asyncEachOfLimit.js
blob: 46b08c6e087a223f2b9c7e602a1befce0d55fc21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import breakLoop from './breakLoop.js'

// for async generators
export default function asyncEachOfLimit(generator, limit, iteratee, callback) {
    let done = false
    let canceled = false
    let awaiting = false
    let running = 0
    let idx = 0

    function replenish() {
        //console.log('replenish')
        if (running >= limit || awaiting || done) return
        //console.log('replenish awaiting')
        awaiting = true
        generator.next().then(({value, done: iterDone}) => {
            //console.log('got value', value)
            if (canceled || done) return
            awaiting = false
            if (iterDone) {
                done = true;
                if (running <= 0) {
                    //console.log('done nextCb')
                    callback(null)
                }
                return;
            }
            running++
            iteratee(value, idx, iterateeCallback)
            idx++
            replenish()
        }).catch(handleError)
    }

    function iterateeCallback(err, result) {
        //console.log('iterateeCallback')
        running -= 1;
        if (canceled) return
        if (err) return handleError(err)

        if (err === false) {
            done = true;
            canceled = true;
            return
        }

        if (result === breakLoop || (done && running <= 0)) {
            done = true;
            //console.log('done iterCb')
            return callback(null);
        }
        replenish()
    }

    function handleError(err) {
        if (canceled) return
        awaiting = false
        done = true
        callback(err)
    }

    replenish()
}