petkaantonov / bluebird

:bird: :zap: Bluebird is a full featured promise library with unmatched performance.

Home Page:http://bluebirdjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

.map() continues execution of handlers after cancellation (using concurrency)

nerocrat opened this issue · comments

  1. bluebird version: 3.7.1

  2. Node.js 10.16.0

  3. in bluebird 3.5.3 same to

If mapper returns a native promise, map() may continue to call mappers after cancellation main promise. This should not happen because concurrency is used (all mappers do not have time to start):

Promise.config({
    cancellation: true
});

function test() {
    let array_size = 100;
    let count = 0;
    let task = Promise.map(new Array(array_size), async () => {
        count++;
        if (count === array_size) console.log('all handlers were called');
        return Promise.delay(10);

    }, {concurrency: 10})

    setTimeout(() => {
        task.cancel();
    }, 10);
}

let tests_count = 100;
while (tests_count--) {
    test();
}

The console output:

all handlers were called
all handlers were called
...

This is a heisenbug, I can not reproduce it in its pure form without understanding the source code.
Correct behavior without native promises:

Promise.config({
    cancellation: true
});

function test() {
    let array_size = 100;
    let count = 0;
    let task = Promise.map(new Array(array_size), () => {
        count++;
        if (count === array_size) console.log('all handlers were called');
        return Promise.delay(10);

    }, {concurrency: 10})

    setTimeout(() => {
        task.cancel();
    }, 10);
}

let tests_count = 100;
while (tests_count--) {
    test();
}

Сonsole is empty.

in this situation, in theory, it does not matter which promise is returned by the mapper, so this behavior is not obvious to me.

I use a translator, sorry