Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View all pending promises in javascript

In my tests, sometimes I get timeouts, and it would be very useful to see what where the promises that were pending before the timeout, so that I know what promises have the most chances of being in an "always pending state".

Is there a way to do that ?

Here's an example code :

Promise.resolve().then(function firstFunction() {
    console.log(1);
    return 1;
}).then(function () {
    return new Promise(function secondFunction(resolve, reject) {
        // NEVER RESOLVING PROMISE
        console.log(2);
    });
}).then(function thirdFunction() {
    // function that will never be called
    console.log(3);
})

setTimeout(function timeoutTest() {
    const pendingPromises = [];// ??????????? how do I get the pendingPromises
    console.log(pendingPromises);
    process.exit();
}, 5000);

I would like, if possible, to get in pendingPromises the name of the function and stacktrace of the promise secondFunction, since it is the one that will never resolve.

like image 291
edi9999 Avatar asked Oct 20 '25 03:10

edi9999


2 Answers

A promise chain is designed progressively to deliver values down its success path or a "reason" down its error path. It is not designed to be enquired at some arbitrary point in time for a "snapshot" the state of individual promises that are assimilated by it.

Therefore, a promise chain offers no "natural" way to do what you ask.

You need to contrive a mechanism for :

  • registering promises of interest.
  • tracking each registered promise's state (if not already provided by the promise implementation).
  • retreiving, on demand, the registered promises, filtered by state.

A constructor along these lines will do the job :

function Inspector() {
    var arr = [];
    this.add = function(p, label) {
        p.label = label || '';
        if(!p.state) {
            p.state = 'pending';
            p.then(
                function(val) { p.state = 'resolved'; },
                function(e) { p.state = 'rejected'; }
            );
        }
        arr.push(p);
        return p;
    };
    this.getPending  = function() {
        return arr.filter(function(p) { return p.state === 'pending'; });
    };
    this.getSettled = function() {
        return arr.filter(function(p) { return p.state !== 'pending'; });
    };
    this.getResolved = function() {
        return arr.filter(function(p) { return p.state === 'resolved'; });
    };
    this.getRejected = function() {
        return arr.filter(function(p) { return p.state === 'rejected'; });
    };
    this.getAll  = function() {
        return arr.slice(0); // return a copy of arr, not arr itself.
    };
};

The only methods required by the question are .add() and .getPending(). The others are provided for completeness.

You can now write :

var inspector = new Inspector();

Promise.resolve().then(function() {
    console.log(1);
}).then(function() {
    var p = new Promise(function(resolve, reject) {
        // NEVER RESOLVING PROMISE
        console.log(2);
    });
    return inspector.add(p, '2');
}).then(function() {
    // function that will never be called
    console.log(3);
});

setTimeout(function() {
    const pendingPromises = inspector.getPending();
    console.log(pendingPromises);
    process.exit();
}, 5000);

fiddle

The use of Inspector isn't confined to promises assimilated by promise chains. It could be used for any arbitrary set of promises, for example a set to be aggregated with Promise.all() :

promise_1 = ...;
promise_2 = ...;
promise_3 = ...;

var inspector = new Inspector();
inspector.add(promise_1, 'promise 1');
inspector.add(promise_2, 'promise 2');
inspector.add(promise_3, 'promise 3');

var start = Date.now();
var intervalRef = setInterval(function() {
    console.log(Date.now() - start + ': ' + inspector.getSettled().length + ' of ' + inspector.getAll().length + ' promises have settled');
}, 50);

Promise.all(inspector.getAll()).then(successHandler).catch(errorHandler).finally(function() {
    clearInterval(intervalRef);
});
like image 66
Roamer-1888 Avatar answered Oct 21 '25 15:10

Roamer-1888


I suggest using library such as Bluebird that is ~6x times faster than native promises, offers useful warnings and additional useful methods like - timeout which might help you with this issue.

like image 21
Lukas Neicelis Avatar answered Oct 21 '25 16:10

Lukas Neicelis