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.
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.
- Exact duplicate of Monitoring pending async operations in Node.js promised environment? – Bergi Commented Sep 1, 2016 at 14:11
- Wow.. you are terribly confused... There is no way to return the synchronous timeline once you get into the promises (AKA asynchronous timeline). – Redu Commented Sep 1, 2016 at 19:38
- They could be some features around it, it just is like à timeline and all links are explicit. It could be possible to wrap promises so that you get this sort if information. – edi9999 Commented Sep 1, 2016 at 19:41
- For example github./emberjs/ember-inspector/pull/76 – edi9999 Commented Sep 1, 2016 at 19:43
2 Answers
Reset to default 6A 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 pleteness.
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);
});
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.