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

BREAKING(async): simplify deadline() logic, remove DeadlineError and improve errors #5058

Merged
merged 22 commits into from
Jun 21, 2024

Conversation

iuioiua
Copy link
Contributor

@iuioiua iuioiua commented Jun 17, 2024

What's changed

This PR:

  1. Ensures that all thrown/rejected errors within @std/async APIs are DOMExceptions, with the appropriate AbortError or TimeoutError error names.
  2. Simplifies deadline() by relying on abortable().
  3. Removes DeadlineError for deadline(), as it's no longer needed.
  4. Clarifies the error message when one of these functions is called and the AbortSignal is already aborted.

Why was this change been made?

These changes were made to:

  1. Ensure this package's APIs are consistent in how they throw errors.
  2. Reduce the number of moving parts.
  3. Reduce the need to import an additional custom error, DeadlineError.
  4. Improve the clarity of errors and therefore help with troubleshooting.

Migration guide

If using deadline() compare the error with DOMException instead of DeadlineError when handling errors.

- import { deadline, type DeadlineError } from "@std/async";
+ import { deadline } from "@std/async";

  try {
    await deadline(promise, 1_000);
  } catch (error) {
-   if (error instanceof DeadlineError && error.message === "Deadline") {
+   if (error instanceof DOMException && error.name === "TimeoutError") {
      // Handle error
    }
  }

Related

Depends on denoland/deno#23842

@github-actions github-actions bot added the async label Jun 17, 2024
@iuioiua iuioiua marked this pull request as ready for review June 17, 2024 09:24
@iuioiua iuioiua requested a review from kt3k as a code owner June 17, 2024 09:24
@kt3k
Copy link
Member

kt3k commented Jun 17, 2024

The main consequences of these changes are that the error type has changed from DeadlineError to DOMException and the error message from Deadline to The signal has been aborted. Deadline error has been removed as it's no longer used.

I don't understand why we want to make this change. Currently the user can distinguish whether the promise is aborted by signal or aborted by deadline by catching the error. Now they can't do it.

@iuioiua
Copy link
Contributor Author

iuioiua commented Jun 17, 2024

You can compare using error.name === "AbortError" or error.name === "TimeoutError", similar to AbortSignal.timeout(). I've clarified my initial comment. Perhaps, we can update the documentation as well.

@kt3k
Copy link
Member

kt3k commented Jun 17, 2024

You can compare using error.name === "AbortError" or error.name === "TimeoutError", similar to AbortSignal.timeout().

Oh, this sounds nice.

I've clarified my initial comment. Perhaps, we can update the documentation as well.

Sounds a good idea. Can you update the doc examples and test case to demonstrate this?

Copy link

codecov bot commented Jun 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.70%. Comparing base (15ec8df) to head (fbab337).
Report is 3 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5058   +/-   ##
=======================================
  Coverage   92.70%   92.70%           
=======================================
  Files         482      482           
  Lines       38713    38723   +10     
  Branches     5462     5457    -5     
=======================================
+ Hits        35888    35898   +10     
  Misses       2770     2770           
  Partials       55       55           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

async/deadline_test.ts Outdated Show resolved Hide resolved
@iuioiua iuioiua requested a review from kt3k June 20, 2024 00:03
@iuioiua
Copy link
Contributor Author

iuioiua commented Jun 21, 2024

I've decided to revert the use of signal.throwIfAborted(), as it throws the reason, which is a string, instead of an error with the message as the reason.

@iuioiua iuioiua marked this pull request as draft June 21, 2024 03:07
@iuioiua iuioiua changed the title BREAKING(async): align better with browser behavior BREAKING(async): remove DeadlineError and improve thrown/rejected errors Jun 21, 2024
@iuioiua iuioiua changed the title BREAKING(async): remove DeadlineError and improve thrown/rejected errors BREAKING(async): simplify deadline() logic, remove DeadlineError and improve thrown/rejected errors Jun 21, 2024
@iuioiua iuioiua changed the title BREAKING(async): simplify deadline() logic, remove DeadlineError and improve thrown/rejected errors BREAKING(async): simplify deadline() logic, remove DeadlineError and improve errors Jun 21, 2024
@iuioiua
Copy link
Contributor Author

iuioiua commented Jun 21, 2024

I've tweaked the direction of this PR and re-written the descript. @kt3k, please take a look once more.

@iuioiua iuioiua marked this pull request as ready for review June 21, 2024 03:35
@0f-0b
Copy link
Contributor

0f-0b commented Jun 21, 2024

I've decided to revert the use of signal.throwIfAborted(), as it throws the reason, which is a string, instead of an error with the message as the reason.

I think it's better to always just throw the reason itself, to be consistent with Web APIs like fetch and navigator.locks.request.

@iuioiua
Copy link
Contributor Author

iuioiua commented Jun 21, 2024

I think it's better to always just throw the reason itself, to be consistent with Web APIs like fetch and navigator.locks.request.

This code does, wrapped in a DOMException. Do you see any spots where it doesn't?

async/mod.ts Show resolved Hide resolved
async/delay.ts Outdated Show resolved Hide resolved
Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
@0f-0b
Copy link
Contributor

0f-0b commented Jun 21, 2024

This code does, wrapped in a DOMException. Do you see any spots where it doesn't?

Here the reason (which is usually already an "AbortError" DOMException) is implicitly converted to a string and used as the message of another exception. That is no longer the reason itself.

@kt3k
Copy link
Member

kt3k commented Jun 21, 2024

Maybe ac.abort() method suppose the reason should be an error object instead of string?

@iuioiua
Copy link
Contributor Author

iuioiua commented Jun 21, 2024

Oh, I see. Thank you. I've made some adjustments, which made things even cleaner. PTAL.

if (signal.aborted) {
return Promise.reject(createAbortError(signal.reason));
}
if (signal.aborted) return Promise.reject(signal.reason);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

On 2nd thought. Maybe this should throw. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

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

This looks fine to me

Copy link
Member

@kt3k kt3k left a comment

Choose a reason for hiding this comment

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

LGTM

I think the removal of wrapping of abort reason is a good move towards Web standard alignment. Thanks @0f-0b for the ideas!

@iuioiua iuioiua merged commit e561d36 into main Jun 21, 2024
15 checks passed
@iuioiua iuioiua deleted the async-use-timeout branch June 21, 2024 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants