2

JavaScriptはシングルスレッドであることが保証されていますか? javascript はシングル スレッドですが、まだ注意事項があることが明らかになりました。

次の疑似コードが常に予測可能かどうか疑問に思っていました (私は jQuery を「使用しています」)。

var lastReq;
$('#button').click(function()
{
  if (lastReq) lastReq.abort();
  lastReq = $.ajax(...);
});

クリック イベントとアボートの間に、サーバーからのデータが送信され、イベント キューにイベントが置かれた可能性があります。これが中止の直前に発生すると、ajax 投稿の成功イベントがトリガーされます。この可能な競合状態を実際にテストする方法がわかりません。

誰でもこれがどのように機能するか考えていますか? または、準備された例でこれをテストする方法は?

4

2 に答える 2

1

編集:リクエストを中止するとすぐに、ブラウザはそれをリッスンしなくなります。したがって、イベント キュー内の応答に到達すると、それを破棄する必要があると思います。


ただし、問題が発生した場合は、次の方法を試すことができます。

実行する必要がなくなったことを検出した場合は、成功関数 + URL をチェックして、それ自体をキャンセルできますか?

たとえば、(このようにするべきだと言っているわけではありません。jqXHR リクエストに何も添付しようとはしていません):

var numReq = 0, lastReq;

$('#button').on('click', function(e) {
    if (lastReq) { lastReq.abort(); }
    numReq ++;
    lastReq = $.ajax({
        success : function(d, s, x) {
            if (x.reqNum < numReq) { return; }
        }
    });
    lastReq.reqNum = numReq;
});

私の理解では、ボタンのクリックが完了するまで ajax イベントはイベント キューに追加されないため、(理論的には) ajax の後に reqNum を設定することを心配する必要はありません ...


次のコードも試しました。

var numReq = 0, lastReq, timer = 100,
    c = setInterval(function() {
        if (lastReq) { lastReq.abort(); }
        numReq ++;
        lastReq = $.ajax({
            url     : 'index.html',
            cache   : false,
            success : function(d, s, x) {
                if (x.reqNum < numReq) { console.log('it happens'); }
            }
        });
        lastReq.reqNum = numReq;
    }, timer);

タイマーを変更して、ページの読み込み時間に (できるだけ近づけて) 一致させようとします。私は「それが起こる」ということはありませんでした。

于 2012-04-20T16:25:12.493 に答える
1

この回避策が本当に便利で防弾になるかどうかはわかりませんが (私は創造的になろうとしています)、jQuery 1.5 ajax メソッドは遅延オブジェクトlastReqを返すため、state()利用可能なメソッドがあります

http://api.jquery.com/deferred.state/から

deferred.state() メソッドは、Deferred オブジェクトの現在の状態を表す文字列を返します。Deferred オブジェクトは、次の 3 つの状態のいずれかになります。

...

"resolved" : Deferred オブジェクトは解決された状態です。つまり、オブジェクトに対して deferred.resolve() または deferred.resolveWith() が呼び出され、doneCallbacks が呼び出された(または呼び出される過程にある)ことを意味します。

コードを次のようにリファクタリングできます

var lastReq;
$('#button').click(function() {
     if (lastReq) {
         if (lastReq.state() === "resolved") {
             return false; /* done() of the previous ajax call is in the process of
                              being called. Do nothing and wait until the state 
                              is resolved */
         }
         else {
             lastReq.abort(); 
         }
     }

     lastReq = $.ajax(url).done(function() {
          /* do something */
          lastReq = null; 
     });
});

これが作業のアイデアを提供するのに役立つことを願っていますが、この種の回避策は本当に必要ないと思います

于 2012-04-20T16:30:18.750 に答える