javascript - 順番 - ajaxレスポンスの中で返されたjsファイルの実行




jqxhr (6)

注意:

  • @ すでにあなたの質問に答えました - 彼の最初の点を見てください。
  • Bastosの答えを強化するためにも、@ ytsクレジットを与える必要があります。

したがって、次のようにsearch_regulations.jsスクリプトで問題を解決する必要があります。

$(document)
  // Detach the event handler to prevent multiple/repeat triggers on the target elements.
  .off('click.toggleActive', '.browse-ctp__filters-data .include, .exclude')
  // Attach/re-attach the handler.
  .on('click.toggleActive', '.browse-ctp__filters-data .include, .exclude', function(){
    ... put your code here ...
  });

しかし、この答えを書く私の主な意図は、あなたのスクリプトの問題を見せることです。

そしてあなたが好奇心が強いなら、私はこのデモで使用したスクリプトを少し修正しました。

https://codepen.io/anon/pen/RBjPjw.js

私はjQuery 3.2.1を使用しているHTML5アプリケーションを持っています。

アプリケーションの一部(検索機能)では、私はajaxリクエストを行います。 ajaxリクエストからの応答はHTMLであり、これはアプリケーションと同じサーバー上でホストされているjsファイルにリンクする<script>タグを含みます。

したがって、ajaxコードは次のようになります - ajaxリクエストを作成し、ID #ajaxContentを使用してdivに応答を書き込むために:

$.ajax({
    url: $('#searchRegulations').attr('action'),
    type: 'post',
    cache: false,
    data: $('#searchRegulations').serialize()
 }).done(function (response, status, xhr) {
        if (response) {
            $('main .content').hide();
            $('#ajaxContent').html(response).show();
            return false;
        }
    }
});

#ajaxContentを調べると、 <script>タグがajaxレスポンスに含まれていることがわかります。

私はまた/js/search_regulations.jsが正しくロードされていることを確認するために自分のネットワークタブをチェックして、それは200の応答を与えています:

search_regulations.js中には、 search_regulations.jsにあるいくつかのフィルタを切り替えるjqueryがあります。

問題は、このコードが約50%の時間しか働かないように見えることです。 それが動作すると、 .browse-ctp__filters-data内の要素にclass .activeを追加/削除し、ID #tmpFilters隠しフォームに書き込むことで、いくつかのフィルタボタンの状態を切り替えることができます。

スクリプトが "発射"していることを確認するために、私はconsole.log('search_regulations.js firing');という行に入れましたconsole.log('search_regulations.js firing'); スクリプトが機能するかどうかに関係なく、 毎回コンソールに表示されます。

見知らぬ人は、ajaxレスポンスがページに書き込まれた後、コードをコンソールに切り取って貼り付けると、 いつも期待どおりに機能するということです。

これは、スクリプトがページに表示される方法に問題がありますか?

私は以下のスクリプトを貼り付けましたが、ブラウザ/ Ajaxレスポンスの処理方法ではなく、コードに問題があるとは思わない:

$(function() {  

console.log('search_regulations.js firing');

/* toggle the active (applied) state on browse by filters */
/* @link https://stackoverflow.com/questions/48662677/switch-active-class-between-groups-of-include-exclude-buttons */
$(document).on('click', '.browse-ctp__filters-data .include, .exclude', function(){

    var $this = $(this);

    // Split name into array (e.g. "find_355" == ["find", "355"]) 
    var arr = $this.attr('name').split('_');


    // Toggle active class
    $this.toggleClass("active");
    if ($this.siblings().hasClass("active")) {
      $this.siblings().removeClass("active")
    }

    // Remove any existing instances of the filter from hidden form
    $('#tmpFilters input[value="exclude_'+arr[1]+'"]').remove();
    $('#tmpFilters input[value="find_'+arr[1]+'"]').remove();

    // If a filter has been applied then add it to hidden form
    if ($this.hasClass('active')) {
        $('#tmpFilters').append('<input type="hidden" name="tmpFilter[]" value="'+$this.attr('name')+'">');
    }
});    
}); 

バウンティについての注意点:

私は解決すべき些細な問題ではないので、恩恵を申し出ました。誰も実行可能な答えを与えていないという事実によって実証されました。 私は正しい答えが期待されます:

  1. jsfiddleまたはそれに相当するもので実証できます。
  2. どのように/なぜそれが動作するのか説明する。
  3. ajaxレスポンスはHTMLとjsであることを理解してください。 jsはレスポンスのHTML要素に作用します。 そのため、HTMLとjの両方をレスポンスに含める必要があります。「jsをグローバルファイルに追加する」とは異なります(私はjsをグローバルにしたくありません。アプリケーションのさまざまな部分で異なる可能性があります)。
  4. タイムアウト( setTimeoutなど)を使用しないでください。 ユーザーがボタンのようなUI要素と対話してタイムアウト前に HTMLレスポンスで返され、したがってjsが起動された場合、これは単に今までと同じ問題につながります。 だから、それは私が懸念している限り有効な解決策ではありません。
  5. HTML5 / jqueryでこの問題を解決できない場合は、理由を説明し、それを処理するための代替方法を提案してください。

ajaxを介して返されたHTMLとスクリプトタグを表示するjsfiddle:

いくつかの人々がフィドルやデモを求めてきました。 2人が同じ結果を得ることはありません。これは質問の要点です。だから、もともとは2つの人がいませんでした。 #ajaxContentに書き込まれたHTMLが返されます: http://jsfiddle.net/v4t9j32g/1/ : #ajaxContent - これは、ブラウザのdevツールがajaxレスポンスの後に表示するものです。 返されるコンテンツの長さは、フィルタボタンの負荷を戻すキーワード検索機能への応答であるため、さまざまです。 また、このHTMLレスポンスには<script src="/js/search_regulations.js"></script>という行が含まれています。 それは問題のあるjsがあるところで、その質問の全内容が上記の質問に表示されています - console.log('search_regulations.js firing')を含むビット


要件について

問題の解決方法は、HTML5 / jQuery、または以前のHTMLバージョンとネイティブJavascriptの組み合わせのいずれかを使用して利用できます。 jQueryのようなライブラリを使用する唯一の理由は、古いブラウザを同じレベルのサポートにしたり、バグを修正したり、開発者のグループ間で標準的なフレームワークを共有したりするためです。

また、私の意見では、問題を解決するために必要な数行のコードをどこに配置するかは問題ではなく、ページの下部、ページの下部、または頻繁にリロードされるAjaxレスポンスペイロード内の賞金。

問題について

実際のトリックは、クリックイベントの発生を達成するために使用するメソッドにあります。繰り返されるAjaxレスポンスにあるスクリプトの中でそれを実行することが、あなたのケードをある時点で失敗させる原因になります。

Ajaxリクエストが発生するたびに、レスポンスのスクリプトは新しいイベントリスナを追加します。 これらは、何らかの理由でメモリが不足したり、イベントスタックが枯渇したり、イベントが競合状態になったりするなど、ブラウザが失敗するまで継続的に集計されます。

ソリューションについて

したがって、問題の解決策は、Ajaxの要求/応答が発生するたびにイベントを追加することを避けることです。 これは簡単な「捕捉フェーズイベント委任」(残念なことに頻繁には使用されない)によって簡単に解決できるタスクです。

イベントリスナーは、「ドキュメント」ノード自体または「html」要素または「body」要素となる上位ノードの1つに1回だけ追加されるため、最初のページの後に常にDOMに存在する1つの要素負荷。

この要素は、現在(または現在ロードされている)Ajax要求によってロードされているページのすべてのクリックをキャプチャする役割を担います。この要素は、ページの全期間にわたって動作します。 /私はいくつかの提案を参照してくださいイベントを破壊する。 まあそれはおそらく同様に動作しますが、ブラウザエンジンでより多くの作業負荷を生成し、より多くのメモリを消費し、より多くのコードを必要とし、全体的に遅く、不必要に難しいとは言い難くなります。

コードサンプル

私はあなたのための2つのCodePenの例をセットアップしました:

Delegation1はHEADセクションにイベント処理コードを持っていますが、制約やその他の未知の癖がなければ、この種の問題を処理するのが私の推奨する方法です。 このバージョンのメリットは、短く/速く、メンテナンス可能なコードです。

Delegation1

Delegation2はAjaxレスポンスのイベント処理コードを持ち、HTML / JSが継続的にロードされるという要件を満たす必要があります。 リスナーを一度インストールするだけで、複数のイベントのレースとオーバーラップを避けることができます。

Delegation2

例のJavascriptコードには関連するコメントが記載されていますので、これを可能な限りシンプルにし、他の同様のケースでは再利用できるように、実装された戦略を説明するのに十分なはずです。

これらの例は古いブラウザで書かれていますが、新しいブラウザでは、 element.matches(selector)などのより強力なAPIがイベントの委任に非常に役立ちます。 私は意図的に広範なサポートのためにそれを使用することを避けた。


これをあなたのajax paramsコールに追加すると、すべてが正常になると考えられました。

非同期:false


コメントに誰もが話していたことに加えて、私はそれを答えに入れようとします。

イベント駆動型

JSはイベント駆動型であるため、イベントが発生したときにスクリプトを実行して機能を実行させるためにスクリプトをロードする必要はありません。 より良いアプローチは、ページロードに必要なものすべてをロードし、イベントリスナーを追加することです。これにより、ユーザーエクスペリエンスが向上し(HTTPリクエストが少なくなります)、コードの適合性が大幅に向上します。

TL; DR

一般的に私はあなたのhtmlファイルでそれのような何かをする:

<script src="/js/main.js">  
<script src="/js/search_regulations.js" async>  <!-- bonus tip! google "async script tag" -->

これにより、必要なすべてのjがロードされます。

search_regulations.jsは、jQuery on必要なイベントリスナーをメソッドに追加する必要がありますが、スクリプトがイベントリスナーを追加したときにhtmlが存在しないため、 thisを確認することをお勧めします。

なぜこれは良いですか?

  • 今では、あるファイルが別のファイルを読み込む非常に簡単なケースがあります。 将来的には、より多くの機能や複雑なコードを追加したいかもしれません。 これは、お互いを読み込むスクリプトのチェーンを持っているときにデバッグするのは面倒です。
  • ユーザーがsearch_regulations.jsファイルのロードが要求されるまで待つ必要があります。モバイルネットワーク上にある場合、ファイルのサイズが大きくなり、ユーザーエクスペリエンスが低下する可能性があります。
  • search_regulations.js使用してアプリケーション上でコードを再利用することは可能search_regulations.js

私が思う問題は次のようなものです:1.同じ機能をトリガーに含めたり除外したりします。 両方を処理する内部のロジックにエラーがあります。 (あなたはそれが時間の50%で働いていると言いましたから)。 2.HTMLを追加した後、DOMを更新してください。

   componentHandler.upgradeDom();

すぐ後

 $('#ajaxContent').html(response).show();

それが役に立てば幸い !!!


私が見る問題の1つは、 onclick同じ要素に複数回バインドしていることです。

jsはajaxリクエストを介して複数回読み込むことができるので、イベントを再度追加する前に、最初に切り離すことが重要です。

もう1つの問題は、 $(document).readyイベントでコードを実行していることです(つまり、HTML文書がロードされ、DOMが準備されているときです)。しかし、おそらく$(window).loadコードを実行する方が良いでしょう$(window).loadイベント(すべてのフレーム、オブジェクト、イメージを含むページが完全にロードされたときに後者を実行する)

$(window).load(function() {  

    console.log('search_regulations.js firing');

    //off: detach the events
    //on: attach the events
    $('.browse-ctp__filters-data .include, .exclude').off('click').on('click', function(){
        ...
    }
}); 




ajax