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

Allow timing out without erroring #30

Merged
merged 11 commits into from Jan 23, 2023
Merged

Conversation

fregante
Copy link
Contributor

@fregante fregante commented Aug 1, 2022

Like we do in element-ready, sometimes timeouts are not errors:

https://github.com/sindresorhus/element-ready#timeout

Thoughts on this proposal before I continue?

@sindresorhus
Copy link
Owner

This would be unexpected as a default, but I'm willing to support it behind an option.

@sindresorhus
Copy link
Owner

Bump

@fregante fregante marked this pull request as ready for review November 25, 2022 08:56
@fregante
Copy link
Contributor Author

Did I miss anything?

index.js Show resolved Hide resolved
reject(message);
} else {
const errorMessage = message ?? `Promise timed out after ${milliseconds} milliseconds`;
reject(new TimeoutError(errorMessage));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it worth exporting this helper? I find this pattern in every place where a customizable error is desired:

https://github.com/pixiebrix/pixiebrix-extension/blob/36a70a95a6979fa1145292ffc7624f296aa07fa0/src/utils/expectContext.ts#L25-L44

reject(createError(`Promise timed out after ${milliseconds} milliseconds`, message))

Copy link
Owner

Choose a reason for hiding this comment

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

👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I haven't done that yet, I haven't thought of any API to specify both message and constructor. I'll publish it under the name as-error unless you have better suggestions. All "create-" and "cast-" options were taken because until recently Error subclassing was not a thing.

Side note: I think specifying a whole error instance isn't ideal, what do you think? Maybe it should be:

error: 'Custom Message' // uses default TimeoutError
// or
error: 'CustomConstructorError' // uses default message
// or
error: [CustomConstructorError, 'Custom Message'] // calls new CustomConstructorError('Custom Message')

The alternative would be to reinstantiate error: new MyError('soup') via new error.constructor(error.message) but that might be unexpected?

Copy link
Contributor Author

@fregante fregante Dec 27, 2022

Choose a reason for hiding this comment

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

I'm considering releasing a more generic "error utils" package with https://github.com/refined-github/refined-github/blob/951f267db9441ae084ee660725d878bc1717bf5d/source/helpers/abort-controller.ts#L11 too. I saw p-timeout also has similar abort logic.

@sindresorhus
Copy link
Owner

Any thoughts on this versus having a separate option? For example, throwOnTimeout. Seems I have done that once before: https://github.com/sindresorhus/p-queue#throwontimeout

readme.md Show resolved Hide resolved
readme.md Outdated Show resolved Hide resolved
reject(message);
} else {
const errorMessage = message ?? `Promise timed out after ${milliseconds} milliseconds`;
reject(new TimeoutError(errorMessage));
Copy link
Owner

Choose a reason for hiding this comment

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

👍

@fregante
Copy link
Contributor Author

Note: this is breaking + there's another breaking change awaiting us in a comment (Node 18 LTS)

Default: `'Promise timed out after 50 milliseconds'`

Specify a custom error message or error.
Specify a custom error message or error to throw when it times out:
Copy link
Owner

Choose a reason for hiding this comment

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

This needs to be changed in the TS comment too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now if only there was a way to automate this 😜

Done

@sindresorhus
Copy link
Owner

Can you make it non-breaking? Just add a stub in the TS docs. I don't think it's worth doing a major release just for this.

@fregante
Copy link
Contributor Author

fregante commented Jan 5, 2023

I thought you asked to rename the option?

I can revert that change in this PR though, sure

@sindresorhus
Copy link
Owner

Yes, I forgot to say rename and keep compatibility. I can add the compatibility if you don't want to.

@sindresorhus
Copy link
Owner

I can revert that change in this PR though, sure

No, the new name is an improvement.

@fregante
Copy link
Contributor Author

fregante commented Jan 5, 2023

I left the rename out of this PR for now, I think it'd be easier to rename separately for tracking, documentation and discussion. The release notes can then point to the specific PR for that. I can work on that PR too

@sindresorhus sindresorhus changed the title Timeout without error Allow timing out without erroring Jan 21, 2023
@sindresorhus
Copy link
Owner

The return type is now incorrect if message: false. So the types need to reflect that when message: false the return type is ReturnType | undefined.

@fregante
Copy link
Contributor Author

fregante commented Jan 21, 2023

I'm afraid I can't type that. It takes me a while to set up conditional returns 😳 Also Options currently depends on ReturnType, but with that change ReturnType must depend on Options

I added a failing test for now

@sindresorhus
Copy link
Owner

I'm afraid I can't type that. It takes me a while to set up conditional returns 😳 Also Options currently depends on ReturnType, but with that change ReturnType must depend on Options

Looks ok? ⬇️

8d85700

@fregante
Copy link
Contributor Author

fregante commented Jan 23, 2023

Oh great! Tests pass so all good

By the way why are there two return types (I'm not talking about "undefined")?

@sindresorhus sindresorhus merged commit 45405e7 into sindresorhus:main Jan 23, 2023
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.

None yet

2 participants