2010-03-22 16 views
21

Tôi muốn thực hiện một yêu cầu Ajax có phản hồi bằng JSON. Vì vậy, tôi đã yêu cầu Ajax này:Làm thế nào để gọi lại một hàm trên 404 trong yêu cầu JSON ajax với jQuery?

$.ajax({ 
    url: 'http://my_url', 
    dataType: "json", 
    success: function(data){ 
     alert('success'); 
    }, 
    error: function(data){ 
     alert('error'); 
    }, 
    complete: function(data) { 
     alert('complete') 
    }}) 

Mã này hoạt động tốt nhưng khi url của tôi gửi cho tôi một mã HTTP 404, không có callbacks được sử dụng, thậm chí gọi lại hoàn chỉnh. Sau khi nghiên cứu, đó là vì dataType của tôi là 'json' nên 404 trả về là HTML và phân tích cú pháp JSON không thành công. Vì vậy, không có gọi lại.

Bạn có một giải pháp để gọi hàm gọi lại khi 404 được nâng lên không?

EDIT: hoàn thành gọi lại không gọi là trả về là 404. Nếu bạn muốn một URL wit 404 bạn có thể gọi: http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697 thì URL này có vấn đề.

Trả lời

19
$.ajax({ 
    url: 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697', 
    dataType: "json", 
    success: function(data) { 
     alert('success'); 
    }, 
    error: function(data) { 
     alert('error'); 
    }, 
    complete: function(xhr, data) { 
     if (xhr.status != 0) 
      alert('success'); 
     else 
      alert('fail'); 
    } 
}) 
+4

không bạn có nghĩa là: "hoàn thành: function (trạng thái, văn bản) {" –

+0

1 Vâng, cảm ơn! –

+1

Tôi cũng cố gắng gọi lại, nhưng gọi lại đầy đủ, nó cũng không gọi nữa: ( Tôi cập nhật câu hỏi của mình với giải pháp này và giải thích thêm – shingara

1

Đơn giản là vì dataType được đặt thành "json"? Nếu vậy, hãy thử thay đổi nó để text và đánh giá JSON mình:

$.ajax({ 
    url: 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697', 
    dataType: 'text', 
    success: function(data, status, xmlHttp) { 
     try { 
      data = eval('(' + data + ')'); 
      alert('success'); 
     } catch (e) { 
      alert('json parse error'); 
     } 
    }, 
    error: function(xmlHttp, status, error) { 
     alert('error'); 
    }, 
    complete: function(xmlHttp, status) { 
     alert('complete'); 
    } 
}); 
+0

Điều này không thành công ngay cả khi nó hoạt động như trên URL http://twitter.com/status/user_timeline/shingara.json?count=3&callback=jsonp1269278524295&_=1269278536697 – shingara

+0

Điều gì sẽ xảy ra nếu bạn dùng thử mà không có 'callback = jsonp ...' trong URL? Ví dụ: http://twitter.com/status/user_timeline/shingara.json?count=3&_=1269278536697 –

9

Với cấu hình của bạn jQuery sử dụng jsonp để vận chuyển dữ liệu. Thao tác này hoạt động bằng cách chèn động một phần tử tập lệnh và đặt URL thành giá trị được chỉ định. Dữ liệu được máy chủ trả về sau đó được đánh giá là JavaScript - thường gọi đến cuộc gọi lại được cung cấp. Nếu máy chủ trả về 404, nội dung rõ ràng là không có JavaScript và gọi lại không bao giờ được gọi. Một số trình duyệt hỗ trợ trình xử lý lỗi trên thẻ tập lệnh, được gọi trong các tình huống này. Thật không may IE không hỗ trợ điều này. Cách tốt nhất để phát hiện lỗi là dựa vào thời gian chờ.

Trong trường hợp của bạn, bạn nên chỉ định tùy chọn timeout bổ sung, điều này làm cho trình xử lý lỗi được gọi nếu cuộc gọi lại không được gọi đúng lúc (trường hợp này là phản hồi 404).

$.ajax({ 
    url: 'http://my_url', 
    timeout: 2000, // 2 seconds timeout 
    dataType: "json", 
    success: function(data){ 
    alert('success'); 
    }, 
    error: function(data){ 
    alert('error'); 
    }, 
    complete: function(data) { 
    alert('complete') 
    } 
}); 
+0

Giải pháp hết giờ không được giải quyết. Gọi không có gì sau khi vượt qua :( – shingara

+0

Tương tự ở đây, tôi chỉ kích hoạt lỗi mọi lúc mặc dù nó nhận được dữ liệu –

+0

Không chắc chắn câu trả lời này đang làm tất cả các con đường ở đây trên -1. –

2

Bạn có nghĩ rằng vấn đề không phải với DataType nhưng với yêu cầu tên miền chéo mà bạn không được phép thực hiện?

Đoạn code dưới đây hoạt động như mong đợi khi bạn yêu cầu dữ liệu từ cùng một tên miền và không khi bạn đang làm cho các yêu cầu cross-domain:

function handle404(xhr){ 
    alert('404 not found'); 
} 

function handleError(xhr, status, exc) { 
    // 0 for cross-domain requests in FF and security exception in IE 
    alert(xhr.status); 
    switch (xhr.status) { 
     case 404: 
      handle404(xhr); 
      break; 
    } 
} 

function dumbRequest() { 
    var url = 'http://twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697'; 
    url = 'http://twitter.com/';  
    url = '/mydata.json';  
// url = 'mydata.json';  
    $.ajax(
     {url: url, 
     dataType: 'json', 
     error: handleError} 
    ); 
} 
+0

Vấn đề là lỗi không bao giờ gọi. Không phải là vấn đề giữa nhiều miền: ( – shingara

1

Bạn có biết rằng mặc dù trạng thái HTTP là 404, thì cơ thể thực sự là JSON hợp lệ? Ví dụ, this link có JSON sau:

jsonp1269278524295({"request":"/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_=1269278536697","error":"Not found"})

Như vậy, bạn nên kiểm tra xem dữ liệu của bạn có error tài sản trong phạm vi chức năng gọi lại bình thường.

CẬP NHẬT: rõ ràng, mặc dù nội dung của trang này là JSON hợp lệ, trình duyệt (tôi đã kiểm tra trong Firefox) không thực hiện điều đó, rất có thể vì nó là một 404. Bởi vì jQuery có thêm một script phần tử (vì vấn đề tên miền chéo), trình bao bọc JSONP của nó không bao giờ được gọi, và kết quả là, không phải là các callback của bạn. Vì vậy, trong ngắn hạn, tôi không nghĩ rằng có một cách để đối phó với điều này mà không cần thêm thủ công yếu tố kịch bản đó và kiểm tra xem chức năng gọi lại được xác định trước của bạn đã được gọi sau đó hay chưa.

0

Đây là cách tôi giải quyết vấn đề này. Tôi kiểm tra các dữ liệu trả về cho các lỗi trước khi cố gắng sử dụng nó. Những gì được hiển thị dưới đây chỉ là một mẫu mà bạn có thể mở rộng để phù hợp hơn với yêu cầu của bạn. Đây cũng coi outs thời gian phiên và kịch bản khác ...

gọi ban đầu của tôi:

$.ajax({ type: 'POST', 
    url: '../doSomething', 
    data: 'my data', 
    success: function(data) { 
     if (HasErrors(data)) return; 
     var info = eval('(' + data + ')'); 
     // do what you want with the info object 
    }, 
    error: function(xmlHttpRequest) { 
     ReportFailure(xmlHttpRequest); 
    } 
    }); 

Và các chức năng hai helper:

function HasErrors(data) { 
    if (data.search(/login\.aspx/i) != -1) { 
    // timed out and being redirected to login page! 
    top.location.href = '../login.aspx'; 
    return true; 
    } 
    if (data.search(/Internal Server Error/) != -1) { 
    ShowStatusFailed('Server Error.'); 
    return true; 
    } 
    if (data.search(/Error.aspx/) != -1) { 
    // being redirected to site error reporting page... 
    ShowStatusFailed('Server Error. Please try again.'); 
    return true; 
    } 
    return false; 
} 

function ReportFailure(msg) { 
    var text; 
    if (typeof msg == 'string') { 
    text = msg; 
    } 
    else if (typeof msg.statusText == 'string') { 
    if (msg.status == 200) { 
     text = msg.responseText; 
    } 
    else { 
     text = '(' + msg.status + ') ' + msg.statusText + ': '; 
     // use the Title from the error response if possible 
     var matches = msg.responseText.match(/\<title\>(.*?)\<\/title\>/i); 
     if (matches != null) 
     { text = text + matches[1]; } 
     else 
     { text = text + msg.responseText; } 
    } 
    } 
    // do something in your page to show the "text" error message 
    $('#statusDisplay') 
    .html('<span class="ui-icon ui-icon-alert"></span>' + text) 
    .addClass('StatusError'); 
} 
1

Chỉ cần đối mặt cùng một vấn đề, và thấy another question đã đề cập rằng jQuery-JSONP (jQuery Plugin) hỗ trợ catchin lỗi g 404 hoặc như họ mô tả: "phục hồi lỗi trong trường hợp thất bại mạng hoặc phản ứng JSON vô hình thành"

Và nó hoạt động hoàn hảo :)

Đây là của tôi (giản thể) mã cho lấy thông tin chi tiết về một đoạn video YouTube thông qua JSONP:

$.jsonp(
{ 
    url: "https://gdata.youtube.com/feeds/api/videos/ee925OTFBCA", 
    callbackParameter: "callback", 
    data: 
    { 
     alt: "jsonc-in-script", 
     v: "2" 
    }, 
    success: function(json, textStatus) 
    { 
     console.log("WEEEEEEEE!"); 
    }, 
    error: function(xOptions, textStatus) 
    { 
     console.error(arguments); 
    } 
}); 
+0

Đây là một giải pháp tuyệt vời cho câu hỏi thực tế được hỏi. Đó là một sự xấu hổ mà thư viện dường như đã ngừng phát triển. Có giải pháp tương tự cho các phiên bản jQuery hiện đại không? –

0

Tiếp theo giải pháp đang làm việc tốt cho tôi :)

$.ajax({ 
    url: 'http://my_url', 
    dataType: "json", 
    success: function(data){ 
     alert('success'); 
    }, 
    error: function(data){ 
     alert('error'); 
    },complete: function(xhr, data) { 
     if(data==="parsererror"){ 
      alert('404'); 
     } 
    } 
}); 
4

Nếu bạn muốn xử lý lỗi khi truy cập vào API Twitter với Javascript và jsonp bạn cần phải bao gồm tham số suppress_response_codes trong yêu cầu của bạn. Điều này làm cho tất cả các phản hồi từ API Twitter phản hồi với một phản hồi 200 OK và bao gồm một lỗi. Sau đó, bạn cần kiểm tra xem phản hồi có bao gồm tham số error hay không.

$.ajax({ 
    url: "https://api.twitter.com/1/users/show.json", 
    dataType: 'jsonp', 
    jsonp: "callback", 
    data: { 
    screen_name: "simongate1337", 
    suppress_response_codes: true // <- Important part 
    }, 
    success: function(data) { 
    if(data.error) { 
     console.log("ERROR: "+data.error); 
    } else { 
     console.log("Success, got user " + data.screen_name); 
    } 
    } 
}); 
3

Sử dụng statusCode -Option

$.ajax({ 
    url: 'http://my_url', 
    dataType: "json", 
    statusCode: { 
     404:function(){ 
      alert("I could not find the informations you requested."); 
     } 
    } 
    success: function(data){ 
     alert('success'); 
    }, 
    error: function(data){ 
     alert('error'); 
    }, 
    complete: function(data) { 
     alert('complete') 
    }}) 
Các vấn đề liên quan