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

Clean cancel #843

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

Clean cancel #843

wants to merge 5 commits into from

Conversation

kkntl
Copy link

@kkntl kkntl commented Sep 7, 2021

I have a suggestion about cleaner error handling, if you like.
(Note that this is my first pull request ever, sorry if I do something wrong)

  1. Cancel loading a Page if the parent Document was unmounted.
    I know that react-pdf is not meant to be used like this anyway, but it seems it would be an easy fix.
    (commit "cancel Page load if Document destroyed")
  2. Cancel loading a file from the filesystem (FileReader) if the Document is unmounted.
    (commit "abort file load on document reload/unmount")
  3. Another test component, to test Page "independant" of Document
    (commit "add test for Page outside Document")

Testing:

1. "cancel Page load if Document destroyed"

  • load any PDF file
  • check the new checkbox "Page outside of Document"
  • click "remove Document" (at the top, in my new test component)
  • click "remove Page" (or alternatively: click "next")
  • click "re-mount Page"

BEFORE:
TypeError: "this.messageHandler is null"

NOW:
callback .onLoadError("Attempted to load a page, but the document was destroyed")

2. "abort file load on document reload/unmount"

  • check the new checkbox "Page outside of Document"
  • check the new checkbox "unmount Document on file load"
  • load a PDF from a file

BEFORE:
"Warning: Can't perform a React state update on an unmounted component"

NOW:
no error in console (file load was aborted, setState wasn't called)

@wojtekmaj wojtekmaj self-requested a review September 13, 2021 21:23
@wojtekmaj wojtekmaj self-assigned this Sep 13, 2021
@wojtekmaj wojtekmaj added the enhancement New feature or request label Sep 13, 2021
@wojtekmaj
Copy link
Owner

Woo, lots of goodness in this PR!

I'm especially curious about the FileReader.abort() thing - didn't know that's possible! I think this deserves to be cherry picked to a separate PR for clarity.

Please allow more time for me to review - extremely busy in personal life recently.

src/Page.jsx Outdated
// eslint-disable-next-line no-underscore-dangle
if (pdf && pdf._transport && pdf._transport.destroyed) {
this.setState({ page: false });
this.onLoadError('Attempted to load a page, but the document was destroyed');
Copy link
Owner

Choose a reason for hiding this comment

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

onLoadError expects Error.

Suggested change
this.onLoadError('Attempted to load a page, but the document was destroyed');
this.onLoadError(new Error('Attempted to load a page, but the document was destroyed'));

Copy link
Author

Choose a reason for hiding this comment

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

changed it

src/Document.jsx Outdated
Comment on lines 88 to 94
// If pdfjs loading is in progress, let's destroy it
if (this.loadingTask) this.loadingTask.destroy();

// If FileReader loading is in progress, let's abort it
if (this.loadFromFileTask) {
this.loadFromFileTask.abort();
}
Copy link
Owner

Choose a reason for hiding this comment

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

Not a fan of this formatting inconsistency, but honestly, that should have been linter's job.

Copy link
Author

Choose a reason for hiding this comment

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

changed it

Comment on lines 166 to 171
return {
promise,
abort: () => {
reader.abort();
},
};
Copy link
Owner

Choose a reason for hiding this comment

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

I'm wondering, if perhaps making the API consistent with make-cancelable-promise by changing abort to cancel wouldn't be a bettter choice.

Copy link
Author

Choose a reason for hiding this comment

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

Both ok for me. I am thinking: 'cancel' is something like "I did the request, but I don't want it anymore, don't send what ever you have, no matter if finished or not" (which is what cancelable-promise does). "Abort" on the other hand is "Stop what you are doing right now". But from our perspective I guess what we want indeed is the same in both cases: don't call any callbacks. So 'cancel' would make sense.

Copy link
Author

Choose a reason for hiding this comment

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

changed it in an extra commit

konstantin.knuetel added 2 commits September 17, 2021 15:57
- call onLoadError() with Error()
- inline if() for code consistency
@wojtekmaj wojtekmaj force-pushed the main branch 14 times, most recently from 5e59480 to 41d6126 Compare November 22, 2021 13:42
@wojtekmaj wojtekmaj force-pushed the main branch 3 times, most recently from ccad668 to 6bb29a9 Compare January 19, 2022 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants