JavaScript 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.

Answer:1

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);
});
Answer:2

I've got following piece of html code: <div class="header-menu hide-for-small"> <ul id="primary-menu" class="subtext"> <li id="menu-item-993"><a>X</a></li&...

I've got following piece of html code: <div class="header-menu hide-for-small"> <ul id="primary-menu" class="subtext"> <li id="menu-item-993"><a>X</a></li&...

  1. change hover element
  2. change element on hover css
  3. change child element hover
  4. change color element hover
  5. change another element on hover
  6. change other element on hover
  7. change other element on hover css
  8. change different element on hover
  9. change child element on hover css
  10. change another element on hover css
  11. change pseudo element on hover
  12. change after element on hover
  13. change element color when hover css
  14. change different element on hover css
  15. change before element on hover
  16. change inner element on hover
  17. change parent element on hover
  18. change cursor on element hover
  19. change element content on hover
  20. change element size on hover

I'm calling js function every 2 seconds where on certain condition I want to update div on the view. <div id="ball_{{ballIndex}}">{{ball}}</div> on ng controller var myCounter = ...

I'm calling js function every 2 seconds where on certain condition I want to update div on the view. <div id="ball_{{ballIndex}}">{{ball}}</div> on ng controller var myCounter = ...

My function below returns an object containing the sorted playerPoints passed in via the "array of objects" parameter. Without modifying the passed in array, is there a more efficient/performant way ...

My function below returns an object containing the sorted playerPoints passed in via the "array of objects" parameter. Without modifying the passed in array, is there a more efficient/performant way ...

I tried in my chrome debug console: >function m(){function toString(){return "abc"}} undefined >new m().toString() "[object Object]" I expect it to print "abc". Why?

I tried in my chrome debug console: >function m(){function toString(){return "abc"}} undefined >new m().toString() "[object Object]" I expect it to print "abc". Why?