4

ここに私のAJAX関数があります:

/**
 * Send an AJAX request
 *
 * @param url      The URL to call (located in the /ajax/ directory)
 * @param data     The data to send (will be serialised with JSON)
 * @param callback The function to call with the response text
 * @param silent   If true, doesn't show errors to the user
 * @param loader   The element containing "Loading... Please wait"
 */
AJAX = function(url,data,callback,silent,loader) {
    var a,
        attempt = 0,
        rsc = function() {
            if( a.readyState == 4) {
                if( a.status != 200) {
                    if( a.status > 999) { // IE sometimes throws 12152
                        attempt++;
                        if( attempt < 5)
                            send();
                        else if( !silent) {
                            alert("HTTP Error "+a.status+" "+a.statusText+"<br />Failed to access "+url);
                        }
                    }
                    else if(!silent) {
                        alert("HTTP Error "+a.status+" "+a.statusText+"\nFailed to access "+url);
                    }
                }
                else {
                    callback(JSON.parse(a.responseText));
                }
            }
        },
        to = function() {
            a.abort();
            attempt++;
            if( attempt < 5)
                send();
            else if( !silent) {
                alert("Request Timeout\nFailed to access "+url);
            }
        };
    data = JSON.stringify(data);
    var send = function() {
        if( loader && attempt != 0) {
            loader.children[0].firstChild.nodeValue = "Error... retrying...";
            loader.children[1].firstChild.nodeValue = "Attempt "+(attempt+1)+" of 5";
        }
        a = new XMLHttpRequest();
        a.open("POST","/ajax/"+url,true);
        a.onreadystatechange = rsc;
        a.timeout = 5000;
        a.ontimeout = to;
        a.setRequestHeader("Content-Type","application/json");
        a.send(data);
    };
    send();
};

一般的な考え方は、リクエストを 5 回まで試行することです。IE が異常な HTTP エラー (12xxx) で失敗したり、サーバーが応答しないことがあります。

私が抱えている問題は、abort()呼び出しが接続を中止しているように見えないことです。テストするために、単純な PHP スクリプトを作成しました。

<?php
    sleep(60);
    touch("test/".uniqid());
    die("Request completed.");
?>

touch()呼び出しは、現在のファイルを作成します。uniqid()変更時刻を見ると、sleep(60)終了時刻がわかります。

予想される動作:

リクエストが送信され
ます。5 秒後、テキストが「Error... Retying... Attempt 2/5」に変わります。
上記を Attempt 5/5 まで繰り返し、失敗します。
PHP ファイルへの 5 回の呼び出しが中止され、"test" フォルダーに 5 秒間隔で 5 つのファイルが存在するか、ignore_user_abort がオフになっているために存在しません。

観察された動作 (IE9):

リクエストが送信され
ます 試行テキストが表示され、必要に応じて変更されます
5 回試行した後、エラー メッセージが表示されます
5 分間、ページを読み込めません。
サーバー上には、1 分間隔で 5 つのファイルがあります。

サーバー側では、「タイムアウト」エラーメッセージがブラウザに表示されてから数分後にリクエスト 3、4、および 5 が送信されているため、これをどうすればよいかわかりません。

違いがある場合、AJAX 呼び出しを行うページは iframe にあります。iframe をリロードします (を使用iframe.contentWindow.location.reload()しても問題は解決しません。これら 5 つのリクエストが通過するのを待ちます。

なぜこうなった?どうすれば修正できますか?

編集:開発者ツールを使用してテストを再度実行し、ネットワーク アクティビティを監視しました。結果は次のとおりです。

URL          Method   Result     Type   Received  Taken   Initiator
/ajax/testto          (Aborted)              0 B  < 1 ms (Pending...)
/ajax/testto          (Aborted)              0 B  125 ms (Pending...)
/ajax/testto          (Aborted)              0 B  125 ms (Pending...)
/ajax/testto          (Aborted)              0 B  125 ms (Pending...)
/ajax/testto          (Aborted)              0 B  124 ms (Pending...)
4

4 に答える 4

4

問題はそれであるように思われ、timeoutまだontimeoutいくつかの実装の一部ではありません:

var hasTimeout = 'timeout' in new XMLHttpRequest(); // false

少なくとも、Chrome16やFirefox7にはありません。そして、true要件があれば、これは返されるはずです。

timeout属性はその値を返す必要があります。最初は、その値はゼロでなければなりません。

どちらも2010年9月7日からXHR2仕様の一部になっています。ただし、「レベル2」の仕様は2008年2月25日から存在し、まだ「作業ドラフト」であるため、実装が仕様に合わせて最新であるという保証はありません。


onabort利用可能なものがない場合は、代わりにandを使用して試すことができsetTimeoutます(コメントで述べたように):

// snip

to = function() {
    attempt++;
    if( attempt < 5)
        send();
    else if( !silent) {
        console.log("Request Timeout\nFailed to access "+url);
    }
};

// snip

var send = function() {
    if( loader && attempt != 0) {
        loader.children[0].firstChild.nodeValue = "Error... retrying...";
        loader.children[1].firstChild.nodeValue = "Attempt "+(attempt+1)+" of 5";
    }
    a = new XMLHttpRequest();
    a.open("POST","/ajax/"+url,true);
    a.onreadystatechange = rsc;
    setTimeout(function () {     /* vs. a.timeout */
        if (a.readyState < 4) {
            a.abort();
        }
    }, 5000);
    a.onabort = to;              /* vs. a.ontimeout */
    a.setRequestHeader("Content-Type","application/json");
    a.send(data);
    console.log('HTTP Requesting: %s', url);
};

// snip

例: http: //jsfiddle.net/AmQGM/2/-は終了する?delay=2はずですが、?delay=10有効期限は5回試行されます。

于 2012-01-25T00:08:54.650 に答える
0

私は同じ問題を抱えていました.PHPセッションの問題であることが判明しました。セッションが開いている場合、同じセッションからの他のすべてのリクエストは待機する必要があります。

<?php
    session_write_close();
    sleep(60);
    touch("test/".uniqid());
    die("Request completed.");
?>

もちろん、セッションを開始していない場合、これは役に立ちません:)

于 2012-09-30T14:38:14.917 に答える
0

リクエストを中止する前に、設定を試してください

a.onreadystatechange = function() {};

その後、abort の呼び出しに関するチェックも追加します。

if( a.readyState > 0 && a.readyState < 4 ) {
    a.abort();
}
于 2012-01-27T17:23:16.217 に答える
0

コードを実行すると、エラー c00c023f が発生しました。ググってみたところ、こんな回答が出てきました。

http://www.enkeladress.com/article.php/internetexplorer9jscripterror

これは、あなたが経験していることと非常によく似ています。

これは、同じ問題を解決するSOの質問です(これも上記のリンクに基づいていますが、追加情報があります):IE 9 Javascript error c00c023f

于 2012-02-02T06:14:56.813 に答える