krux / postscribe

Asynchronously write javascript, even with document.write.
MIT License
986 stars 156 forks source link

Error when calling cancel: args.stream.abort is not a function #478

Open jrzerr opened 5 years ago

jrzerr commented 5 years ago

I'm using React and I want to be able to cancel the postscribe load if my component unmounts before the script is loaded. Why? Because React will complain, rightly so, if I try and do things with an unmounted component because in some cases, when the afterAsync callback is called, the component is gone. I need to cancel it from triggering, naturally I'd want to cancel it within my componentWillUnmount hook.

Looking into the documentation, it looks like postscribe(...) returns an object that you can call .cancel() on. So I did that, but the error I get is:

args.stream.abort is not a function

This is referring to the WritableStream class and looking into it, I couldn't see anywhere that an abort() method exists.

Here is how I'm using the code in a React component in componentDidMount I call this:

componentDidMount () {
    this.postscribeCancel = postscribe(this.el, '<script type="text/javascript" src="https://great.url.here"></script>', {
      afterAsync: () => {
          this.setState({
            show: true
          })
      }
    })
}

this.el is an element reference from the DOM. After the script loads, I want to show the element so that's why I call setState.

Then, to properly cancel this loading, I presumed I could do this:

  componentWillUnmount () {
    if (this.postscribeCancel) {
      this.postscribeCancel.cancel()
    }
  }

But when that fires, I get this error in the JS console: Uncaught TypeError: args.stream.abort is not a function

That cancel function from the postscribe code is here: https://github.com/krux/postscribe/blob/master/src/postscribe.js#L172

and for easy reference looks like this:

    cancel: () => {
      if (args.stream) {
        args.stream.abort();
      } else {
        args[1] = doNothing;
      }
    }

So I guess my ultimate question is, if abort() doesn't really exist on the WritableStream object, is there any other suggestion on how I can cancel to stop the afterAsync from triggering when the component is unmounted before the postscribe script loads.

jrzerr commented 5 years ago

My expectation would also be that even if the postscribe script loads successfully, I should be able to call this.postscribeCancel.cancel() and have no error thrown, it would just be a no-op at that point because there is nothing left to cancel.

explodingrabbit commented 5 years ago

I'm having the same problem.

sethyates commented 5 years ago

Pull requests welcome