Closed jodal closed 9 years ago
Forgot to add, I'm using When.js 3.7.0, Node.js 0.10.25.
Real code in question is https://github.com/mopidy/mopidy.js/blob/master/test/mopidy-test.js#L225-L248.
@jodal Ah, yes, you're right. Thanks for the detailed report. The problem is that settle
is taking a shortcut for already-settled promises--a shortcut that doesn't mark the rejected promise as having been observed. It should be an easy fix ... stay tuned :)
@jodal Fixed in master. Feel free to give it a try. I'll get a 3.7.1 release together shortly.
Thanks for the quick fix! I tested, and it looks good :-)
@jodal No prob, thanks for reporting it. 3.7.1 was released with this fix.
I still seem to have this problem when one of the rejected promises comes from a function exported by a node module that uses it's own when
. Both the parent module and the child module require the latest version 3.7.2
.
I resolved the issue by adding when
as a peer dependency for the child module but I still think it should be looked at...
@nickdima Hmm, are you sure they are both using 3.7.2? I could see this happening if there is an older version of settle
being called somewhere.
There is another possible explanation. Many promise impls (including when.js) distrust other implementations: they use fast/private code path when dealing with their own promises, and slower/safer paths when dealing with foreign promises. This is true across different versions of the same library or even two copies of the same version, since most use an instanceof
check to identify their own promises.
One thing when.js does with foreign promises is to never call then
in the current microtick, to protect the current call stack from side effects that might happen in the foreign promise's then
. In your situation, maybe that extra microtick is just long enough to trigger an unhandled rejection report.
Question: Do you then see a subsequent "Handled previous rejection" message logged?
I have faced the same issue. Maybe I am missing something, since I'm not so familiar with promises. Here's the snippet:
const url = require('url');
const when = require('when');
function validate(ast, file, preferred, done) {
const links = ['http://google.com', 'http://example.com', 'http://i-will-raise-rejection.promise'];
const promises = [];
for (let i in links) {
const link = links[i];
const options = {
method: 'GET',
timeout: 5000,
uri: link,
resolveWithFullResponse: true,
};
const promise = rp(options);
promises.push(promise);
promise
.then(r => handleResponse(r, file, link))
.catch(() => handleError(file, link));
}
// here I want to wait for every request to finish, before running the callback:
when.settle(promises).then(() => done());
}
That works as expected, except this warning:
Potentially unhandled rejection [1] RequestError: Error: ETIMEDOUT at new RequestError (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request-promise/lib/errors.js:14:15) at Request.RP$callback as _callback at self.callback (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request/request.js:200:22) at emitOne (events.js:90:13) at Request.emit (events.js:182:7) at null._onTimeout (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request/request.js:775:12) at Timer.listOnTimeout (timers.js:92:15) Potentially unhandled rejection [3] RequestError: Error: ETIMEDOUT at new RequestError (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request-promise/lib/errors.js:14:15) at Request.RP$callback as _callback at self.callback (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request/request.js:200:22) at emitOne (events.js:90:13) at Request.emit (events.js:182:7) at null._onTimeout (/Users/sobolev/Documents/github/remark-lint-is-link-active/node_modules/request/request.js:775:12) at Timer.listOnTimeout (timers.js:92:15)
I am using:
"request-promise": "^3.0.0",
"when": "^3.7.7"
I guess it also has to do something with: https://gist.github.com/benjamingr/0237932cee84712951a2
I'm not sure I've misunderstood something, or if this is weakness in the unhandled rejection checker: If I settle an array which contains rejected promises, these cause "potentially unhandled rejection" without a matching warning later with the same ID. The same behavior is observed with
.then()
and.done()
.Example code:
Output: