2009-08-12 9 views
0

XMLHttpRequest、prevDataLength、nextreadPosおよびinProgress(ロッキング用)にグローバル変数を使用せずに、JavaScript処理でまだ処理されていないXMLHttpRequest responseTextの一部のみがonprogress/onreadystatechangeハンドラにありますか?グローバル変数を使用しないでXMLHttpRequestレスポンスの未処理部分を処理する方法はありますか?

問題は次のとおりです。AJAX(XMLHttprequestのresponseTextの現在の値)を使用して取得したデータのうち、現在受信した部分に基づいてWebページを更新します。私は、サーバーがデータを送信するとすぐにページを更新したいです(これは、いわゆるHTTP streaming patternです)。私が更新するとき、私は未処理のresponseText部分だけを処理したい。

さらに複雑なのは、responseTextに応答の未完成断片が含まれている可能性があるということです。私はターミネーターを使って簡単にそれに対処できます(私のように)。完全な応答を簡単に抽出することができます。

現在、グローバル変数とロックを使用して、以前の呼び出しが作業を完了していない(新しいデータを処理している)ときにハンドラが呼び出される問題を回避します。次のように私のコードの見た目(簡体字):

function processData(unprocessed, nextReadPos) { 
    var lastLineEnd = unprocessed.lastIndexOf('\n'); 
    if (lastLineEnd !== -1) { 
     var lines = unprocessed.substring(0, lastLineEnd).split('\n'); 
     nextReadPos += lastLineEnd + 1 /* 1 == '\n'.length */; 

     processLines(lines); 
    } // end if 

    return nextReadPos; 
} 

function handleResponse() { 
    ... 
    // here xhr.readyState === 4 && xhr.status === 200 
    // in case we were called before finished processing 
    if (inProgress) { 
     return; 
    } else { 
     inProgress = true; 
    } 

    // extract new whole (complete) lines, and process them 
    while (prevDataLength !== xhr.responseText.length) { 
     if (xhr.readyState === 4 && 
      prevDataLength === xhr.responseText.length) { 
      break; 
     } 

     prevDataLength = xhr.responseText.length; 
     var unprocessed = xhr.responseText.substring(nextReadPos); 
     nextReadPos = processData(unprocessed, nextReadPos); 
    } // end while 
    ... 
    inProgress = false; 
} 
... 
xhr.onreadystatechange = handleResponse; 

私は単純なハンドラを持っている場合、それは例えばのように、パラメータとしてXMLHttpRequestオブジェクトを渡すことで、作業を完了していないときに私は再入力ハンドラから守ることができコードのより大きな断片で使用される表記で

xhr.onreadystatechange = function() { handleResponse(xhr); }; //1 (simultaneous request) 

されるが、その例にはない

httpRequest.onreadystatechange = function() { alertContents(httpRequest); }; //1 (simultaneous request) 

:MozillaのデベロッパーセンターでAJAX/Getting_Started物品の部分 - 「簡単な例ステップ3」の場合1他のグローバル変数の処理方法を教えてください:prevDataLengthnextReadPos。これらは、新しいデータがあるかどうかを判断し、サーバーの応答から完全な「文章」を抽出するために使用されます。

グローバル変数を使用しないで行う方法は?

答えて

1

クリティカルセクションを保護するためにsemaphor /ミューテックスとして使用

まず他の回答、グローバル変数inProgressが、なかったので、私は、自分の質問に答えるのです、とwhile (prevDataLength !== xhr.responseText.length) { ... }ループは全く必要ありません。 William's answerAre mutexes needed in JavaScript?にStackOverflowの質問によれば

Javascriptがユーザに露出ないスレッドがないことを意味リエントラント言語として定義され、実装内のスレッドが存在してもよいです。 setTimeout()などの関数と非同期コールバックは、スクリプトエンジンが実行できるようになるまで待機する必要があります。

これは"Document Object Model (DOM) Level 3 Events W3C Specification"、第1章「ドキュメントオブジェクトモデルイベント」、セクション1.2「イベントのディスパッチとDOMイベントフロー」、最後の段落で説明して同意:

DOMイベントモデルが再入可能です。イベントリスナーは、追加のイベントを送出するアクションを実行することがあります。このようなイベントは同期的に処理され、新しいイベントのイベントディスパッチが完了した後にのみ、イベントリスナをトリガするイベントの伝播が再開されます。

つまり、イベントで発生するすべてのイベントは、次のイベントが処理される前に終了する必要があります。第二に


グローバル変数prevDataLengthnextReadPosは(そしておそらく必要があります)XMLHttpRequestオブジェクトに追加余分なプロパティとして追加することができます。ダグラス・クロックフォードによってPrivate Members in JavaScriptに多少の説明、およびcomp.lang.javascriptよくある質問ノート:: Javascriptをクロージャ内Example 3: Encapsulating Related Functionalityによう

代替ソリューションは、プライベート/静的変数を持つようにクロージャを使用することです。

関連する問題