2009-06-16 31 views
89

Để thêm một số xử lý lỗi cơ bản, tôi muốn viết lại một đoạn mã sử dụng jQuery .getJSON của jQuery để lấy một số ảnh từ Flickr. Lý do để làm điều này là $ .getJSON không cung cấp xử lý lỗi hoặc làm việc với thời gian chờ.jQuery ajax (jsonp) bỏ qua thời gian chờ và không kích hoạt sự kiện lỗi

Vì $ .getJSON chỉ là một trình bao bọc quanh $ .ajax Tôi quyết định viết lại điều và ngạc nhiên bất ngờ, nó hoạt động hoàn hảo.

Giờ đây, niềm vui bắt đầu. Khi tôi cố ý gây ra 404 (bằng cách thay đổi URL) hoặc làm cho mạng bị hết thời gian chờ (do không được kết nối với mạng nội bộ), sự kiện lỗi đó hoàn toàn không cháy. Tôi đang thua lỗ với những gì tôi đang làm sai. Giúp đỡ được nhiều đánh giá cao.

Dưới đây là các mã:

$(document).ready(function(){ 

    // var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL 
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404 

    $.ajax({ 
     url: jsonFeed, 
     data: { "lang" : "en-us", 
       "format" : "json", 
       "tags" : "sunset" 
     }, 
     dataType: "jsonp", 
     jsonp: "jsoncallback", 
     timeout: 5000, 
     success: function(data, status){ 
      $.each(data.items, function(i,item){ 
       $("<img>").attr("src", (item.media.m).replace("_m.","_s.")) 
          .attr("alt", item.title) 
          .appendTo("ul#flickr") 
          .wrap("<li><a href=\"" + item.link + "\"></a></li>"); 
       if (i == 9) return false; 
      }); 
     }, 
     error: function(XHR, textStatus, errorThrown){ 
      alert("ERREUR: " + textStatus); 
      alert("ERREUR: " + errorThrown); 
     } 
    }); 

}); 

tôi muốn thêm rằng câu hỏi này đã được hỏi khi jQuery đang ở phiên bản 1.4.2

Trả lời

85

jQuery 1.5 trở lên có hỗ trợ tốt hơn để xử lý lỗi với yêu cầu JSONP. Tuy nhiên, bạn cần sử dụng phương thức $.ajax thay vì $.getJSON. Đối với tôi, công trình này hoạt động:

var req = $.ajax({ 
    url : url, 
    dataType : "jsonp", 
    timeout : 10000 
}); 

req.success(function() { 
    console.log('Yes! Success!'); 
}); 

req.error(function() { 
    console.log('Oh noes!'); 
}); 

Thời gian chờ dường như thực hiện thủ thuật và gọi trình xử lý lỗi khi không có yêu cầu thành công sau 10 giây.

Tôi cũng đã làm một chút blogpost về chủ đề này.

+23

Tôi vượt quá khó chịu ngay bây giờ mà tôi đã đập đầu chống lại vấn đề này trong 2 ngày và phải mất một số tìm kiếm tối nghĩa trên StackOverflow để tìm ra tôi phải thêm một thời gian chờ vào một yêu cầu tên miền chéo để có được lỗi cháy. Làm thế nào điều này không được đề cập trong tài liệu jQuery? +1 – chrixian

+0

Với giải pháp này, tôi không thể nhận được mã trạng thái, tôi nhận được "timeout" thay vì vậy tôi không thể biết được lỗi thực sự là gì, và không thể xử lý nó tài sản – Tarlog

+10

@ Tarlog: đó là hợp lý. Các yêu cầu JSONP không phải là các yêu cầu Ajax gốc, chúng chỉ đơn giản là các thẻ Javascript '

67

Đây là hạn chế đã biết với việc thực hiện jsonp mẹ đẻ trong jQuery . Các văn bản dưới đây là từ IBM DeveloperWorks

JSONP là một kỹ thuật rất mạnh mẽ cho mashup xây dựng, nhưng, thật không may, nó không phải là một cứu cánh cho tất cả các nhu cầu giao tiếp cross-domain của bạn. Nó có một số hạn chế phải được thực hiện để cân nhắc nghiêm túc trước khi cam kết tài nguyên phát triển. Đầu tiên và trước hết, không có lỗi khi xử lý các cuộc gọi JSONP . Nếu mã chèn động hoạt động, bạn được gọi; nếu không, không có gì xảy ra. Nó không hoạt động âm thầm. Ví dụ: bạn không thể bắt lỗi 404 từ máy chủ. Bạn cũng không thể hủy hoặc khởi động lại yêu cầu. Tuy nhiên, bạn có thể hết thời gian chờ sau khi đợi khoảng thời gian hợp lý . (Future jQuery phiên bản có thể có một tính năng hủy bỏ cho yêu cầu JSONP.)

Tuy nhiên có một jsonp plug-in có sẵn trên GoogleCode cung cấp hỗ trợ cho xử lý lỗi. Để bắt đầu, chỉ cần thực hiện các thay đổi sau đối với mã của bạn.

Bạn có thể tải xuống hoặc chỉ thêm tham chiếu tập lệnh vào trình cắm.

<script type="text/javascript" 
    src="http://jquery-jsonp.googlecode.com/files/jquery.jsonp-1.0.4.min.js"> 
</script> 

Sau đó thay đổi cuộc gọi ajax của bạn như hình dưới đây:

$(function(){ 
    //var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne"; // correct URL 
    var jsonFeed = "http://api.flickr.com/services/feeds/photos_public.gne_______"; // this should throw a 404 
    $.jsonp({ 
     url: jsonFeed, 
     data: { "lang" : "en-us", 
       "format" : "json", 
       "tags" : "sunset" 
     }, 
     dataType: "jsonp", 
     callbackParameter: "jsoncallback", 
     timeout: 5000, 
     success: function(data, status){ 
      $.each(data.items, function(i,item){ 
       $("<img>").attr("src", (item.media.m).replace("_m.","_s.")) 
          .attr("alt", item.title) 
          .appendTo("ul#flickr") 
          .wrap("<li><a href=\"" + item.link + "\"></a></li>"); 
       if (i == 9) return false; 
      }); 
     }, 
     error: function(XHR, textStatus, errorThrown){ 
      alert("ERREUR: " + textStatus); 
      alert("ERREUR: " + errorThrown); 
     } 
    }); 
}); 
+0

Cảm ơn bạn đã trả lời José! Việc thực thi giới hạn của jsonp nguyên gốc trong jQuery là lý do tôi đã thay thế $ .ajax. Tuy nhiên, có vẻ như sau đó vấn đề không phải là $ .getJSON là một wrapper quanh $ .ajax nhưng dataType: jsonp. Đúng không? – Matijs

+0

Đúng vậy. –

+0

Chưa có thời gian cho đến hôm nay. Nó không hoạt động. Tôi nhận được một lỗi, nhưng đó là về nó. Tôi không biết lỗi là lỗiĐược xác định là không xác định. Hiện tại, tôi sẽ kết hợp với $ .ajax và thiếu thông báo lỗi. Javascript là một lớp bổ sung trên đầu trang web cho tôi. Nếu Flickr là xuống hoặc ném thông báo lỗi, chúng tôi sẽ chỉ phải sống với nó bây giờ :) Cảm ơn đề xuất của bạn. – Matijs

8

này có thể là một "nổi tiếng" giới hạn của jQuery; Tuy nhiên, nó dường như không được tài liệu tốt. Tôi đã dành khoảng 4 giờ để cố gắng hiểu tại sao thời gian chờ của tôi không hoạt động.

Tôi đã chuyển sang jquery.jsonp và nó hoạt động như một sự quyến rũ. Cảm ơn bạn.

2

Dường như được giải quyết như của jQuery 1.5. Tôi đã thử mã ở trên và tôi nhận được cuộc gọi lại.

tôi nói "có vẻ là" vì các tài liệu của callback lỗi cho jQuery.ajax() vẫn có các lưu ý sau:

Lưu ý: xử lý này không được gọi cho kịch bản cross-domain và yêu cầu JSONP.

12

Một giải pháp nếu bạn đang mắc kẹt với jQuery 1.4:

var timeout = 10000; 
var id = setTimeout(errorCallback, timeout); 
$.ajax({ 
    dataType: 'jsonp', 
    success: function() { 
     clearTimeout(id); 
     ... 
    } 
}); 
+0

Xin cảm ơn! Làm việc cho tôi – Marek

+2

chỉ là một nhận xét, nó là một giải pháp hợp lệ cho những người bị mắc kẹt với 1,4, nhưng thiết lập biến thời gian chờ của bạn đủ cao, vì vậy bạn không có vấn đề với webservices chậm :). nếu bạn đặt nó thành một giây chẳng hạn, bạn có thể thấy ý tôi là gì, lỗi gọi lại được kích hoạt, trong khi sau đó 1 giây cuộc gọi của bạn vẫn được tìm nạp và gọi hàm thành công. vì vậy chỉ cần ghi nhớ để thiết lập nó đủ cao hợp lý – Sander

+0

@Sander chức năng thành công thậm chí có thể được gọi nếu bạn có một câu trả lời sau 10 giây với thời gian chờ là 5 giây. Gọi '.abort()' trên một jqXHR đang chờ xử lý sau một khoảng thời gian chờ có thể là một cách tốt hơn. – Matijs

1

Các jquery-jsonp jQuery plugin nêu tại Jose Basilio'sanswer bây giờ có thể được tìm thấy trên GitHub.

Đáng tiếc là tài liệu có phần Spartan, vì vậy tôi đã cung cấp một ví dụ đơn giản:

$.jsonp({ 
     cache: false, 
     url: "url", 
     callbackParameter: "callback", 
     data: { "key" : "value" }, 
     success: function (json, textStatus, xOptions) { 
      // handle success - textStatus is "success" 
     }, 
     error: function (xOptions, textStatus) { 
      // handle failure - textStatus is either "error" or "timeout" 
     } 
    }); 

quan trọng Bao gồm callbackParameter trong cuộc gọi $ .jsonp() nếu không tôi đã phát hiện ra rằng callback chức năng không bao giờ được đưa vào chuỗi truy vấn của cuộc gọi dịch vụ (hiện tại là phiên bản 2.4.0 của jquery-jsonp).

Tôi biết câu hỏi này cũ, nhưng vấn đề xử lý lỗi bằng cách sử dụng JSONP vẫn chưa được 'giải quyết'. Hy vọng rằng bản cập nhật này sẽ hỗ trợ người khác vì câu hỏi này được xếp hạng hàng đầu trong Google về "xử lý lỗi jquery jsonp".

+0

tìm đẹp, và tuyệt vời chủ đề này vẫn còn sống sau ba năm… – Matijs

1

Điều gì về việc nghe sự kiện onerror của tập lệnh? Tôi đã có vấn đề này và giải quyết nó bằng cách vá phương pháp jquery nơi thẻ script đã được tạo ra. Đây là một đoạn mã thú vị:

// Attach handlers for all browsers 
script.onload = script.onreadystatechange = function(_, isAbort) { 

    if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) { 

     cleanup(); 

     // Callback if not abort 
     if (!isAbort) { 
      callback(200, "success"); 
     } 
    } 
}; 

/* ajax patch : */ 
script.onerror = function(){ 
    cleanup(); 

    // Sends an inappropriate error, still better than nothing 
    callback(404, "not found"); 
}; 

function cleanup(){ 
    // Handle memory leak in IE 
    script.onload = script.onreadystatechange = null; 

    // Remove the script 
    if (head && script.parentNode) { 
     head.removeChild(script); 
    } 

    // Dereference the script 
    script = undefined; 
} 

Bạn nghĩ gì về giải pháp này? Có khả năng gây ra sự cố tương thích không?

Các vấn đề liên quan