0
votes

I'm learning this bluebird promises library. I've created very simple express app with just one file and one route - GET /test.

Basically my scenerio is that I have promise which have interval inside and resolve after few interval "loops". Interval works every 1 second and after 5 times I clear interval and resolve promise.

But before I would resolve promise from interval I have timeout which should cancel this promise after 3 seconds and therefore stop interval.

My code is:

const express = require('express');
const app = express();
const path = require('path');
const bodyParser = require('body-parser');
const Promise = require('bluebird');

Promise.config({
    warnings: true,
    longStackTraces: true,
    cancellation: true,
    monitoring: true
});

app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));

//promise
const foo = () => {
    return new Promise((resolve, reject) => {
        let index = 0;
        const intervalId = setInterval(() => {
            index++;
            console.log('in interval, index: ', index);
            if(index === 5) {
                clearInterval(intervalId);
                resolve();
            }
        }, 1000);
    });
};

//test route here
app.get('/test', async(req, res) => {
    setTimeout(() => {
        foo.cancel();
    }, 3000);
    try {
        await foo();    
    } catch (e) {
        console.error(e);
    }
    res.send('Completed');
});

app.listen(5000, () => {
    console.log('Listen on port: ', 5000)
});

So first I require express and node packages, then I set bluebird config as they suggest here (because cancellation is disabled by default).

Then I have my foo function which have bluebird promise inside. There is this logic with interval which I mentioned earlier - index number is incrementing and when it is 5 interval will eventually resolve promise.

But before that in my /test route I have timeout which should cancel this promise after 3 seconds.

So expected output is:

in interval, index: 1

in interval, index: 2

in interval, index: 3

Completed

but this actually doesn't work and give me error that it doesn't know what cancel method is:

C:\Users\Admin\Documents\cancellationPromise\bluebirdp\server.js:35

   foo.cancel();

       ^

TypeError: foo.cancel is not a function

EDIT I've changed my /test route to this:

app.get('/test', async(req, res) => {
    let searchPromise = Promise.resolve();
    searchPromise = foo()
        .then(function() {
            console.log('not canceled')
        })
        .catch(function(e) {
            console.log(e);
        })
        .finally(function() {
            if (!searchPromise.isCancelled()) {}
        });

    setTimeout(() => {
        searchPromise.cancel();
    }, 3000);

    res.send('Completed');
});

So now I'm calling cancel on returned promise. Now the behaviour is that it give response after 55ms and then console.log every second not stoping at 3:

enter image description here

Is it possible with bluebird to cancel promise including loops, intervals and other nested promises within it?

1
foo is a function, not a promise. You probably want to call the .cancel() method on the promise object that foo() returns? - Bergi
Oh yes actually - BT101
I changed my code but I'm still not able to cancel this with bluebird please some tips @Bergi - BT101

1 Answers

3
votes

You cancel the Promise, but you never clear the interval. The two things aren't linked properly in your code. It should look like this:

const foo = () => {
  return new Promise((resolve, reject, onCancel) => {
    let index = 0;
    const intervalId = setInterval(() => {
      index++;
      console.log('in interval, index: ', index);
      if(index === 5) {
        clearInterval(intervalId);
        resolve();
      }
    }, 1000);
    onCancel(() => {
      clearInterval(intervalId);
    });
  });
};