JQuery Ajax - วิธีตรวจจับข้อผิดพลาดการเชื่อมต่อเครือข่ายเมื่อทำการโทร Ajax


91

ฉันมีโค้ด Javascript JQuery ที่เรียก Ajax ไปยังเซิร์ฟเวอร์ทุกๆ 5 นาทีเพื่อให้เซสชันเซิร์ฟเวอร์มีชีวิตอยู่และให้ผู้ใช้ล็อกอินอยู่ฉันกำลังใช้$.ajax()วิธีการใน JQuery ดูเหมือนว่าฟังก์ชันนี้จะมีคุณสมบัติ 'ข้อผิดพลาด' ที่ฉันกำลังพยายามใช้ในกรณีที่การเชื่อมต่ออินเทอร์เน็ตของผู้ใช้หยุดทำงานเพื่อให้สคริปต์ KeepAlive ทำงานต่อไป ฉันใช้รหัสต่อไปนี้:

var keepAliveTimeout = 1000 * 10;

function keepSessionAlive()
{
    $.ajax(
    {
        type: 'GET',
        url: 'http://www.mywebapp.com/keepAlive',
        success: function(data)
        {
            alert('Success');

            setTimeout(function()
            {
                keepSessionAlive();
            }, keepAliveTimeout);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown)
        {
            alert('Failure');

            setTimeout(function()
            {
                keepSessionAlive();
            }, keepAliveTimeout);
        }
    });
}

เมื่อฉันเรียกใช้ฉันจะได้รับป๊อปอัป 'ความสำเร็จ' บนหน้าจอในกล่องแจ้งเตือนทุก ๆ 10 วินาทีซึ่งก็ใช้ได้ อย่างไรก็ตามทันทีที่ฉันถอดปลั๊กสายเคเบิลเครือข่ายฉันไม่ได้รับอะไรเลยฉันคาดว่าฟังก์ชันข้อผิดพลาดจะถูกเรียกและเห็นกล่องแจ้งเตือน 'ความล้มเหลว' แต่ไม่มีอะไรเกิดขึ้น

ฉันถูกต้องหรือไม่หากสมมติว่าฟังก์ชัน 'ข้อผิดพลาด' มีไว้สำหรับรหัสสถานะที่ไม่ใช่ '200' ที่ส่งคืนจากเซิร์ฟเวอร์เท่านั้น มีวิธีตรวจสอบปัญหาการเชื่อมต่อเครือข่ายเมื่อทำการโทร Ajax หรือไม่?


คุณถอดปลั๊กสายเคเบิลเครือข่ายของไคลเอ็นต์หรือสายเคเบิลเครือข่ายของเซิร์ฟเวอร์หรือไม่?
Jeff Sternal

คุณยังคงได้รับการแจ้งเตือน "สำเร็จ" หลังจากถอดปลั๊กการเชื่อมต่อของคุณหรือไม่?
Wilkins

3
@ เจฟฟ์ - เป็นการสูญเสียการเชื่อมต่ออินเทอร์เน็ตที่ไคลเอนต์ซึ่งเป็นสาเหตุของปัญหา สิ่งนี้เกิดขึ้นอย่างไม่น่าเชื่อเนื่องจากลูกค้าบางรายใช้แอปด้วยการเชื่อมต่อไร้สายแบบหลบ ๆ มีคำกล่าวว่า "อย่าประมาทความสามารถของผู้ใช้ปลายทางในการหาวิธีทำลายแอปพลิเคชันของคุณ" ดังขึ้นอย่างแน่นอนที่นี่ :-)
วันอาทิตย์ Ironfoot

@qwertypants - ไม่ไม่มีอะไรเกิดขึ้นเมื่อขาดการเชื่อมต่ออินเทอร์เน็ต (เช่นการถอดสายเคเบิล) แม้ว่าจะพยายาม $ .ajax แต่ฉันเห็นมันใน Firebug
วันอาทิตย์ Ironfoot

มีวิธีตั้งค่าการหมดเวลาสำหรับการพยายามเชื่อมต่อหรือไม่?
axk

คำตอบ:


100
// start snippet
error: function(XMLHttpRequest, textStatus, errorThrown) {
        if (XMLHttpRequest.readyState == 4) {
            // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        }
        else if (XMLHttpRequest.readyState == 0) {
            // Network error (i.e. connection refused, access denied due to CORS, etc.)
        }
        else {
            // something weird is happening
        }
    }
//end snippet

4
นี่ควรเป็นคำตอบที่ได้รับการยอมรับ ในฟังก์ชันข้อผิดพลาดที่คุณระบุให้กับ $ .ajax พารามิเตอร์ตัวแรกจะให้ข้อมูลสถานะทุกประเภท แม้ว่าคุณจะไม่ได้กำหนดระยะหมดเวลาก็ตาม
Mike Spear

และทำเช่นเดียวกันกับแบบฟอร์ม ajax: <form ... data-ajax-failure="YourMethod" ...></form>และตามวิธีการของคุณfunction YourMethod(XMLHttpRequest) { ..same code... }
Matthieu Charbonnier

1
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการXMLHttpRequest.readyStateดูajax_xmlhttprequest_response.asp
stomy

13

คุณก็ควรจะเพิ่ม: ที่ไหนสักแห่งภายในtimeout: <number of miliseconds>, $.ajax({})นอกจากนี้cache: false,อาจช่วยได้ในบางสถานการณ์

$ .ajax ได้รับการบันทึกไว้อย่างดีคุณควรตรวจสอบตัวเลือกที่นั่นอาจพบว่ามีประโยชน์

โชคดี!


1
มีหลายสิ่งที่ไม่ได้บันทึกไว้ใน Ajax และถูกซ่อนไว้อย่างใด :(
Espanta

9

เนื่องจากฉันไม่สามารถทำซ้ำปัญหานี้ได้ฉันจึงแนะนำให้ลองใช้การหมดเวลาในการโทรของ ajax เท่านั้น ใน jQuery คุณสามารถตั้งค่าด้วย $ .ajaxSetup (และจะเป็นแบบสากลสำหรับการโทร $ .ajax ทั้งหมดของคุณ) หรือคุณสามารถตั้งค่าเฉพาะสำหรับการโทรของคุณเช่นนี้:

$.ajax({
    type: 'GET',
    url: 'http://www.mywebapp.com/keepAlive',
    timeout: 15000,
    success: function(data) {},
    error: function(XMLHttpRequest, textStatus, errorThrown) {}
})

JQuery จะลงทะเบียนการหมดเวลา 15 วินาทีในการโทรของคุณ หลังจากนั้นหากไม่มีรหัสตอบกลับ http จากเซิร์ฟเวอร์ jQuery จะดำเนินการเรียกกลับข้อผิดพลาดโดยตั้งค่า textStatus เป็น "หมดเวลา" ด้วยวิธีนี้อย่างน้อยคุณก็สามารถหยุดการโทรของ ajax ได้ แต่คุณจะไม่สามารถแยกความแตกต่างของปัญหาเครือข่ายที่แท้จริงจากการสูญเสียการเชื่อมต่อ


3

สิ่งที่ฉันเห็นในกรณีนี้คือถ้าฉันดึงสายเคเบิลเครือข่ายของเครื่องไคลเอ็นต์และโทรออกตัวจัดการความสำเร็จของ ajax จะถูกเรียกว่า (ทำไมฉันไม่รู้) และพารามิเตอร์ข้อมูลเป็นสตริงว่างเปล่า ดังนั้นหากคุณแยกส่วนการจัดการข้อผิดพลาดจริงคุณสามารถทำสิ่งนี้ได้:

function handleError(jqXHR, textStatus, errorThrown) {
    ...
}

jQuery.ajax({
    ...
    success: function(data, textStatus, jqXHR) {
        if (data == "") handleError(jqXHR, "clientNetworkError", "");
    },
    error: handleError
});

1

หากคุณกำลังทำการข้ามโดเมนให้เรียกใช้ Jsonp มิฉะนั้นข้อผิดพลาดจะไม่ถูกส่งกลับ


0

ใช้

xhr.onerror = function(e){
    if (XMLHttpRequest.readyState == 4) {
        // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
        selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
    }
    else if (XMLHttpRequest.readyState == 0) {
        // Network error (i.e. connection refused, access denied due to CORS, etc.)
        selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
    }
    else {
        selFoto.erroUploadFoto('Erro desconhecido.');
    }

};

(โค้ดเพิ่มเติมด้านล่าง - ตัวอย่างอัปโหลดรูปภาพ)

var selFoto = {
   foto: null,

   upload: function(){
        LoadMod.show();

        var arquivo = document.frmServico.fileupload.files[0];
        var formData = new FormData();

        if (arquivo.type.match('image.*')) {
            formData.append('upload', arquivo, arquivo.name);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'FotoViewServlet?acao=uploadFoto', true);
            xhr.responseType = 'blob';

            xhr.onload = function(e){
                if (this.status == 200) {
                    selFoto.foto = this.response;
                    var url = window.URL || window.webkitURL;
                    document.frmServico.fotoid.src = url.createObjectURL(this.response);
                    $('#foto-id').show();
                    $('#div_upload_foto').hide();           
                    $('#div_master_upload_foto').css('background-color','transparent');
                    $('#div_master_upload_foto').css('border','0');

                    Dados.foto = document.frmServico.fotoid;
                    LoadMod.hide();
                }
                else{
                    erroUploadFoto(XMLHttpRequest.statusText);
                }

                if (XMLHttpRequest.readyState == 4) {
                     selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
                }
                else if (XMLHttpRequest.readyState == 0) {
                     selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);                             
                }

            };

            xhr.onerror = function(e){
            if (XMLHttpRequest.readyState == 4) {
                // HTTP error (can be checked by XMLHttpRequest.status and XMLHttpRequest.statusText)
                selFoto.erroUploadFoto('Erro HTTP: '+XMLHttpRequest.statusText);
            }
            else if (XMLHttpRequest.readyState == 0) {
                 // Network error (i.e. connection refused, access denied due to CORS, etc.)
                 selFoto.erroUploadFoto('Erro de rede:'+XMLHttpRequest.statusText);
            }
            else {
                selFoto.erroUploadFoto('Erro desconhecido.');
            }
        };

        xhr.send(formData);
     }
     else{
        selFoto.erroUploadFoto('');                         
        MyCity.mensagens.push('Selecione uma imagem.');
        MyCity.showMensagensAlerta();
     }
  }, 

  erroUploadFoto : function(mensagem) {
        selFoto.foto = null;
        $('#file-upload').val('');
        LoadMod.hide();
        MyCity.mensagens.push('Erro ao atualizar a foto. '+mensagem);
        MyCity.showMensagensAlerta();
 }
 };

-1

นี่คือสิ่งที่ฉันแจ้งเตือนผู้ใช้ในกรณีที่เครือข่ายของพวกเขาล่มหรือเมื่อการอัปเดตหน้าล้มเหลว:

  1. ฉันมีแท็ก div บนหน้าที่ฉันใส่เวลาปัจจุบันและอัปเดตแท็กนี้ทุกๆ 10 วินาที มีลักษณะดังนี้:<div id="reloadthis">22:09:10</div>

  2. ในตอนท้ายของฟังก์ชั่นจาวาสคริปต์ที่อัปเดตเวลาในแท็ก div ฉันใส่สิ่งนี้ (หลังจากเวลาถูกอัปเดตด้วย AJAX):

    var new_value = document.getElementById('reloadthis').innerHTML;
    var new_length = new_value.length;
    if(new_length<1){
        alert("NETWORK ERROR!");
    }
    

แค่นั้นแหละ! คุณสามารถแทนที่ส่วนแจ้งเตือนด้วยสิ่งที่คุณต้องการได้แน่นอน หวังว่านี่จะช่วยได้


-6

คุณลองสิ่งนี้แล้วหรือยัง?

$(document).ajaxError(function(){ alert('error'); }

ที่ควรจัดการ AjaxErrors ทั้งหมด ฉันได้พบมันนี่ นอกจากนี้คุณยังพบความเป็นไปได้ที่จะเขียนข้อผิดพลาดเหล่านี้ลงในคอนโซล firebug ของคุณ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.