5

I have an external script followed by an inline script at the bottom of my <body>. It looks like the inline script is running before the external script, which isn't supposed to happen, according to this answer:

If you aren't dynamically loading scripts or marking them as defer or async, then scripts are loaded in the order encountered in the page. It doesn't matter whether it's an external script or an inline script - they are executed in the order they are encountered in the page. Inline scripts that come after external scripts have are held until all external scripts that came before them have loaded and run.

Src: https://stackoverflow.com/a/8996894/114855

This is my code:

  <script src="https://checkout.stripe.com/checkout.js"></script>
  <script>
  var handler = StripeCheckout.configure({
    key: 'pk_live_HhFqemZFyEUJVorFzYvjUK2j',
    token: function(res) {
      $('#pay_token').val(res.id);
      $('#pay_email').val(res.email)
      $('#pay_amount').val(parseFloat($("#amount").val())*100);
      $('#pay_description').val($("#description").val());
      $('#pay_real').submit();
    }
  });

  /* .. */
  </script>

</body>

Console is showing that StripeCheckout is not defined (which the external script should define)

Console

This makes sense, since the network tab shows that my external request is still pending. But I'm not sure why the browser didn't wait for checkout.js to be fetched:

Network

Community
  • 1
  • 1
Colin
  • 2,814
  • 5
  • 27
  • 37

2 Answers2

2

The comments to both answers in the quoted question indicate that the accepted answer is not backed by a standards reference (applicable to all commonly encountered browser versions) and indeed may not be true for all browsers, all of the time.

I can confirm that behavior. But there are hints on our feedback pages, that it might only work when test.php is cached. Do you know any spec/reference links about this?

This answer is incorrect. It is not always the case that "dynamically added scripts are executed as soon as they are appended to the document". Sometimes this is true (e.g. for old versions of Firefox), but usually it is not. The execution order, as mentioned in jfriend00's answer, is not determinate

To be completely safe, wait until the DOM is fully rendered before running your script.

Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • Does not [the recommendations for html5](http://www.w3.org/TR/html5/scripting-1.html) determine the script execution order? – Leo Apr 22 '15 at 01:35
  • 1
    @Leo: Does every commonly encountered browser implement the html5 spec? – Eric J. Apr 22 '15 at 01:35
  • Probably not. :-( -- Though the interesting thing here is that Chrome somehow missed it. Looking at the spec it says something like "every script element with a src attribute". A bit misleading I think. – Leo Apr 22 '15 at 01:37
  • I have been slowly watching this go blue over the past several years https://www.modern.ie/en-us/ie6countdown But there's still IE 7, 8, 9..., and older versions of other browser that less-than-fully implement the spec. https://html5test.com/results/desktop.html – Eric J. Apr 22 '15 at 01:40
  • Old browsers does not interest me. I am lucky to say it is just history :-) -- That Chrome missed the standard is worrying me. Do we have to file (another) bug report, or? – Leo Apr 22 '15 at 01:43
  • Well none of the *current generation* browsers fully implement the spec. Chrome did not implement this aspect of the spec apparently. – Eric J. Apr 22 '15 at 02:18
  • From a practical point of view you are right of course, but I think the developers at Google just made a small mistake. (But a very, very unpractical mistake...) – Leo Apr 22 '15 at 02:27
  • @APAD1's comment on the parent question suggests putting the include in the . Does this have any guarantees associated with it? – Colin Apr 22 '15 at 02:46
  • @Colin: No. It may help with some browsers. It's safest to wait until the DOM is fully rendered before relying on the external script. – Eric J. Apr 22 '15 at 04:12
  • @EricJ. Got it, one more question. Can you help me understand how jQuery's $ works? How do they guarantee that $ is defined when the browser reaches a `$(function(){ #DomReady });` statement? Details about that statement: http://learn.jquery.com/using-jquery-core/document-ready/ – Colin Apr 22 '15 at 18:01
  • I'm not sure how it can be absolutely guaranteed on every browser that $ is defined before that code is reached, given the issues highlighted here. That might be worth asking as a new question, referencing this one. Practically, I have never seen it fail. – Eric J. Apr 22 '15 at 18:08
  • @EricJ. I've added that question here: http://stackoverflow.com/questions/29830272/how-to-guarantee-the-jquery-is-initialized – Colin Apr 23 '15 at 17:52
2

Ahha - I've figured it out!

This is part of a rails application running TurboLinks.

TurboLinks dynamically changes the body content instead of creating a new request every time you click a link. This means my script tags are being inserted dynamically, and the guarantee that they're run in order is lost.

Since TurboLinks does not re-evaluate script tags on every request, I think the easiest/best solution here is to include StripeCheckout on every page of my app (not just the one's it's needed on), within the <head>

I also think TurboLinks can resolve this by finding a way to run the scripts in order. I plan to followup with an issue on their github, and will update here accordingly.

Colin
  • 2,814
  • 5
  • 27
  • 37