在<script>标记

时间:2018-02-02 11:46:19

标签: javascript html asynchronous

我是NodeJs开发人员,碰巧有一些Web应用程序。&#xA;我非常熟悉异步代码以及事件循环的工作原理。但是我遇到了一个问题,直到我意识到异步代码在多个脚本标签之间分割时可能会有不同的行为,我才能解决这个问题。&#xA;情况如下

&#xA;&#xA ;
    &#xA;
  • 我在head部分有一个脚本标记,带有一些异步代码。这样的代码期望一些功能存在。该函数应该以同步的方式在第二个脚本标记上声明,因此在异步内容完成时该函数应该存在。
  • &#xA;
  • 第二个脚本标记是100%同步的并且在代码中间创建了一个名为boot的函数。
  • &#xA;
&#xA;&#xA;

让我用一些简化的代码说明它:

&#xA ;&#xA;
  //&lt; script&gt;&#xA; somePromise()&#XA; .then(()=&gt; window.boot())&#xA; //&lt; / script&gt;&#xA; //&lt; ...一些HTML代码和正文&gt;&#xA; //&lt; script&gt;&#xA; window.boot = function(){}&#xA; //&lt; / script&gt;&#xA;  
&#xA;&#xA;

由于promise回调应该异步执行,我希望它转到事件循环并允许其余的同步代码执行。

& #xA;&#xA;

在某些浏览器上,这正如我所料。当我说某些浏览器时,我指的是不同用户在不同计算机上的浏览器,因为即使使用相同的浏览器品牌和版本,行为也会有所不同但是,有些情况下,在第二个第二个脚本标记有机会启动并引发错误之前执行了promise回调。

&#xA;&#xA;

这应该如何在浏览器上运行?每个脚本标签是否都被执行,直到所有代码都被执行,即使是异步代码?如果是这种情况,为什么它适用于其他一些浏览器?

&#xA;&#xA;

提前致谢。

&#xA;

2 个答案:

答案 0 :(得分:2)

HTML5解析器不是同步的。

这是我自己的HTML Parser Threading on MDN部分的重写摘录。请参考原件进行正式治疗和重读。

  

脚本标记[pairs]之间的HTML由nsHtml5StreamParser解析,该onDataAvailable在主线程上执行。

     

解析器运行自己的事件循环,并响应来自主线程的请求以执行OnStopRequestDoDataAvailable处理。处理分别调用doStopRequstDoDataAvailable

     

nsHtml5TreeOpExecutor::RunFlushLoop().输出小DOM树操作,例如将元素创建到主线程中处理的队列中。树操作队列不时使用计时器刷新到主线程**。

     

刷新后,解析器将runnable调度到主线程以处理树添加。主线程中的运行器(或执行程序)调用onFulfilled

  @KarelG在this question中发表的评论称网络数据通常以8Kb块的形式处理。这个问题值得一读。

因此,JavaScript事件循环有时会有机会履行承诺并在解析和执行第二个脚本元素之前执行window.boot处理程序 - 正如您已经发现的那样!

总之,它适用于源代码的网络检索的变幻莫测,使用定时器来启动树构建操作处理的异步HTML解析,以及树构建器可能调用或不调用的任何进一步的异步操作,所有这些都组合在一起创造竞争条件。

竞争条件的失败分支的不可预测性,当调用时未定义@extends('layouts.manage') @section('content') <div class="flex-container m-t-10"> <div class="columns m-l-10"> <div class="row"> <h1 class="title m-l-15">Create New Users</h1> </div> </div> <hr class="m-t-0"> <form action="{{route('users.store')}}" method="POST"> {{csrf_field()}} <div class="col-lg-offset-0 col-md-12 thumbnail"> <div class="form-group"> <label for="name" class="control-label">Name:</label> <input type="text" name="name" class="form-control" id="name" value="{{ old('name')}}" placeholder="Enter your name..."> </div> <div class="form-group"> <label for="email" class="control-label">Email:</label> <input type="text" name="email" class="form-control" id="email" value="{{ old('email')}}" placeholder="Enter your email..."> <small>Your email is confidential with us</small> </div> <div class="form-group"> <label for="password" class="control-label">Password:</label> <input type="password" name="password" class="form-control" id="password" v-if="!auto_password" placeholder="Enter your password..."> <b-checkbox name="auto_generate" class="m-t-15" v-model="auto_password">Auto Generate Password</b-checkbox> </div> </div> </div> <div> <button class="btn btn-md btn-success fa fa-user-plus pull-right"> Create New User</button> </div> </form> <div> <a class="btn btn-warning btn-md fa fa-caret-left pull-left" href="{{route('users.index')}}"> Back</a> </div> </div> @endsection @section('scripts') <script> var app = new Vue({ el: '#app', data: { auto_password: true, } }); </script> @endsection 时,很可能是由于浏览器品牌,网络速度,设备利用率,HTML内容的长度和类型的综合影响,以及HTML解析器计时和计时器。

显而易见的结论是,代码不应该首先建立这种竞争条件。这是不安全的编码实践。谢天谢地,你可以解决它。

答案 1 :(得分:0)

实际上,承诺不是在IE中支持的,所以你可以做的是使用一些外部库,比如bluebirdJS,或者你可以使用一个转换器(babel或另一个)