Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement disabling timeouts #127

Merged
merged 5 commits into from
Apr 22, 2019
Merged

Conversation

stroncium
Copy link
Contributor

Limit maximum timeout, add timeout: false option, fixes #117


@default 10000
*/
timeout?: number;
timeout?: number | false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this in a different TS project yesterday and it didn't seem to work. Are you sure this is correct?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure this works. Just tested quickly on a TS project and seemed like it did.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a new feature, but not experimental. Available since TypeScript 2.0.

index.js Outdated
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const delay = ms => new Promise((resolve, reject) => {
if (ms > 2147483647) { // See #117, https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values
reject(new TypeError('`timeout` can not be greater than 2147483647'));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be a TypeError, since it's a number, as expected. I would either use Error or RangeError.

Also, validation logic like this should be performed towards the top of the constructor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RangeError seems perfect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, not a type error from js perspective, fixed.

It's a side effect(we control) of setTimeout, IMO it's much clearer when it is throw from where the problem lies. Also, this way it handles all possible internal usages of delay in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, I expected this discussion. I even wrote the code to walk around this issue so there will be no need to overgeneralize constructor/docs and enforce stronger dependencies but then deleted it because it felt just too stupid to add 6 lines of code because of issue no one is expected to ever hit(now that false works). But at this point I can bring it back if you want.

Copy link
Contributor Author

@stroncium stroncium Apr 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I little catch though: won't work for numbers higher than ~1e293, but no one will live long enough to know about that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sindresorhus I think Got should also throw at this position.

test/main.js Outdated
response.end(fixture);
});

await t.throwsAsync(ky(server.url, {timeout: 21474836470}).text(), TypeError); // Timeout greater than 2147483647
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should throw synchronously, so that the user immediately knows something is wrong. Should also assert about the error message to be sure it's the error we are expecting.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should throw synchronously

Hmm... People expect a Promise so IMO it should throw asynchronously 🤔

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is input validation, it represents a programmer error, and should cause a crash even if you don't await the promise. Keep in mind that some people use Ky in a fire-and-forget pattern where operational errors are ignored but programmer errors should still bubble up.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then unhandled rejection would pop up.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Promise spec says that Promise-returning functions should always reject, and never synchronously throw.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sholladay It is not input validation on library level tho, it's input validation on setTimeout level. If setTimeout was written correctly and throwing an error on timeouts bigger than const, would you add another check and throw there?

index.js Outdated
@@ -111,7 +111,13 @@ class TimeoutError extends Error {
}
}

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const delay = ms => new Promise((resolve, reject) => {
if (ms > 2147483647) { // See #117, https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that // See #117 is just enough :P

index.js Outdated
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
const delay = ms => new Promise((resolve, reject) => {
if (ms > 2147483647) { // See #117, https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values
reject(new RangeError('`timeout` can not be greater than 2147483647'));
Copy link
Collaborator

@szmarczak szmarczak Apr 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
reject(new RangeError('`timeout` can not be greater than 2147483647'));
reject(new RangeError('The `timeout` option cannot be greater than 2147483647'));

Yanis Benson and others added 2 commits April 22, 2019 03:38
@szmarczak szmarczak changed the title Limit maximum timeout, add timeout: false option, fixes #117 Implement disabling timeouts Apr 22, 2019
@szmarczak szmarczak merged commit e9c807b into sindresorhus:master Apr 22, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement & document a way to disable timeouts
5 participants