Ajaxが重複要求を複数回送信しないようにする

15495 ワード

第一:Ajax反復要求の複数回送信
システムがAjax要求を使用している場合、Ajax反復要求を処理していないため、Ajax要求を複数回繰り返し送信すると、フロントデータに重複ロードの問題が発生します.
ソリューション:
Ajaxリクエストの重複送信を防止するにはどうすればいいですか?
アクティブ・クエリー・ステータスの方法(A、B、jQueryの例)またはツール関数の方法(C、D)で重複操作を除去し、いくつかの例を参照してください.
A.独占型
次のコミットを実行するには、コミット操作が同時に存在し、今回のコミットが完了するまで許可されます.
module.submit = function() {
  if (this.promise_!=undefined && this.promise_.state() === 'pending') {
return } return this.promise_ = $.post('/api/save') }

B.欲張りタイプ
無制限のコミットですが、最後の操作に準じます.すなわち、最後の操作のフィードバックをできるだけ早く与える必要があり、前の操作結果は重要ではない.
module.submit = function() {
  if (this.promise_!=undefined && this.promise_.state() === 'pending') {
    this.promise_.abort()
  }
  // todo
}

たとえば、いくつかのアプリケーションのエントリには、「好き」または「嫌い」のような操作を行う二状態ボタンがあります.押下後すぐにフィードバックを与えなければ、ユーザーの目の焦点はそのボタンに長い間止まる可能性がある.ボタンを押すとすぐにボタンの状態を切り替え、プログラム上でabortで積極的な提出を実現すれば、ユーザー体験を向上させ、サーバのストレスを低減することができ、喜ぶことができます.
C.節制型
どんなに頻繁にコミットされても、任意の2回の有効なコミットの間隔は必ずある時間間隔より大きいか、または等しい.すなわち、一定の頻度で提出される.
module.submit = throttle(150, function() {
  // todo
})

お客様が100ミリ秒ごとに10回のリクエストを送信した場合、このモジュールは6つのみ受信されます(各時間線上距離は150ミリ秒)処理を行います.これもクエリーの競合を解決するオプションの手段です.たとえば、下書きの例をよく知っています.よく観察すると、エディタのblurイベントはすぐに保存をトリガーします.保存ボタンのclickイベントもすぐに保存をトリガーします.しかし、この2つのイベントが数ミリ秒以内に連続的に発生する場合があります.-エディタの内部にフォーカスし、保存ボタンを直接クリックすると、throttleで処理できます.また、resize、scroll、mousemoveなど、throttleを頻繁に使用するイベント処理もあります.
D.怠惰型
任意の2回のコミットの間隔は、有効なコミットを促進するには、指定された時間よりも大きくなければなりません.休みを取らずに仕事をしない.
module.submit = debounce(150, function() {
  // todo
})

また、下書きの例として、エディタ内でctrl+sを押すと、下書きを手動で保存することができます.もしあなたが続けて押すと、プログラムはなぜあなたが続けて押すのか理解していないことを示して、あなたが続けて押すことを放棄するのを待っているだけで、それは続けます.
より多くの記憶の例
方式Cと方式Dは、これらの場合のように、より一般的に使用される場合がある.
  • ゲームで威力の強い高速武器を拾いました.弾丸がスクリーンに直線になるのを防ぐために、throttleで周波数をコントロールすることができます.
  • 弾幕型ゲームでは、射撃キーを挟んで無脳ゲームを行うことを防止するために、debounceで周波数を制御することができます.
  • コンパイルタスクでは、デーモンプロセスは、あるフォルダ内のすべてのファイル(いずれのファイルの変更も再コンパイルをトリガーすることができ、1回の実行に2秒かかる)を監視していますが、git checkoutのような多くのファイルの変更を瞬時に発生させることができます.この場合、簡単なdebounceはコンパイルタスクを1回だけ実行することができます.
  • 方式Cは方式Bと組み合わせて使用することもでき、例えば自動完了コンポーネント(Googleトップページの検索は):
  • ユーザが素早くテキストを入力するとき(特にタイプライター)、throttle keypressイベント処理関数は、テキストドメインの値を抽出するために時間間隔を指定し、すぐに新しいクエリーを行うことができる.
  • 新しいクエリーを送信する必要があるが、前のクエリーが結果を返していない場合、abortが完了していないクエリーをabortし、すぐに新しいクエリーを送信することができる.

  • E.記憶型
    var scrape = memoize(function(url) {
      return $.post('/scraper', { 'url': url })
    })
    

    同じパラメータの場合、その戻りは常に一定であり、毎回同じオブジェクトが返されます.適用例には、内容を貼り付けるときにリンク情報をキャプチャするエディタがあり、memoizeは同じリンクが2回キャプチャされないことを保証します.
    F.累積型
    自動完了イベントを処理するときにこの関数を得たことがあります.連続イベントの処理にも使用できます.連続した複数のコミットを1つのコミットに統合できます.たとえば、次のようにします.
    var request = makePile(5, function() {
        $.post('/', { list: JSON.stringify([].slice.call(arguments)) })
    })
    
    //       
    request({a:1}), request({a:2}), request({a:3}), request({a:4}), request({a:5})
    /* post =>
    list:[{"a":1},{"a":2},{"a":3},{"a":4},{"a":5}]
     */
    

    サンプル実装:
    var makePile = function(count, onfilter, onvalue) {
      var values = [], id = function(value) { return value }
      return function(value) {
        values.push((onvalue || id).apply(this, arguments))
        if (values.length === count) {
          onfilter.apply(this, values)
          values = []
        }
      }
    }
    

    もう1つの蓄積は、動作統計に適用されるなど、時間ではなく回数で行われ、数十以上の類似の動作が瞬時に収集される可能性があります.この場合、pileの構造にdebounceを追加して、大量の重複要求を防止できます(統計は失われません):
    var trackFactory = function(delay, action) {
      var params = [], slice = [].slice
      var touch = debounce(delay, function() {
        if (params.length) {
          action(params)
          params = []
        }
      })
      return function() {
        params.push(slice.call(arguments))
        touch()
      }
    }
    
    var track = trackFactory(550, function(params) {
      // send tracking request
    })
    

    G.サンプリングタイプ
    最近の再構築で連想されるのは、自動ロード(timeline)動作制御に適用できる、上記とは異なる再構築操作です.
    autoload.listen(feeds, 'next', sample(3, function() {
      this.enable()
    }))
    

    sampleが硬化した選択関数である場合(n選択1)、これは実際には次のように動作します.
    O-O-X-O-O-X
    

    ただし、「自動ロード」のアプリケーションでは、(2回の自動、1回の手動):
    X-X-O-X-X-O
    

    この場合、制御は構成の選択関数として定義できます.
    options { sample: (n) => n % 3 !== 0 }
    

    すなわち、次のロードが完了するごとに、3回に2回、次のロードに対して自動ロードが実行される.