jQuery ajax (jsonp)는 시간 초과를 무시하고 오류 이벤트를 발생시키지 않습니다.


89

기본적인 오류 처리를 추가하기 위해 jQuery의 $ .getJSON을 사용하여 Flickr에서 일부 사진을 가져 오는 코드를 다시 작성하고 싶었습니다. 이 작업을 수행하는 이유는 $ .getJSON이 오류 처리를 제공하지 않거나 시간 초과로 작동하지 않기 때문입니다.

$ .getJSON은 $ .ajax를 둘러싼 래퍼이기 때문에 나는 그 일을 다시 작성하고 놀랍게도 완벽하게 작동합니다.

이제 재미가 시작됩니다. 의도적으로 404 (URL 변경)를 발생 시키거나 네트워크 시간 초과 (웹 간 연결되지 않음)를 발생 시키면 오류 이벤트가 전혀 발생하지 않습니다. 나는 내가 뭘 잘못하고 있는지에 대해 잃어 버렸다. 도움을 많이 주시면 감사하겠습니다.

코드는 다음과 같습니다.

$(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);
        }
    });

});

jQuery가 버전 1.4.2 일 때이 질문이 요청되었다고 추가하고 싶습니다.

답변:


86

jQuery 1.5 이상은 JSONP 요청으로 오류 처리를 더 잘 지원합니다. 그러나 $.ajax대신 방법 을 사용해야합니다 $.getJSON. 나를 위해 이것은 작동합니다.

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

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

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

타임 아웃은 10 초 후에 성공적인 요청이 없을 때 트릭을 수행하고 오류 처리기를 호출하는 것처럼 보입니다.

나는 조금 한 블로그 게시물 뿐 아니라이 주제에 있습니다.


23
2 일 동안이 문제에 대해 머리를 부딪 혔고 StackOverflow에서 모호한 검색을 수행하여 오류를 발생시키기 위해 도메인 간 요청에 시간 초과를 추가해야한다는 것을 알아 내려면 지금 당장 짜증이납니다. 어떻게 이것이 jQuery 문서에서 언급되지 않을 수 있습니까? 교차 도메인 jsonp 요청이 정말 드문가요? 어쨌든 고마워요 고마워요 고마워요 +1
chrixian 2011-07-04

이 솔루션을 사용하면 상태 코드를 얻을 수없고 대신 "시간 초과"가 발생합니다. 그래서 실제 오류가 무엇인지 알 수 없으며 속성을 처리 할 수 ​​없습니다.
Tarlog

10
@Tarlog : 논리적입니다. JSONP 요청은 기본 Ajax 요청이 아니라 <script>동적으로 삽입되는 자바 스크립트 태그 일뿐 입니다. 따라서 알 수있는 유일한 것은 상태 코드가 아니라 요청이 실패했다는 것입니다. 상태 코드를 얻으려면 기존 Ajax 요청 또는 기타 교차 도메인 기술을 사용해야합니다.
Husky

1
@Husky가 말했듯이 JSONP로 상태 코드를 가질 수 없으며 이것이 피해야하는 이유라고 생각합니다. 오류를 얻는 유일한 방법은 시간 제한을 두는 것입니다. 이것은 다른 많은 것들과 마찬가지로 jQuery 문서에서 더 잘 설명되어야합니다.
Alejandro García Iglesias 2013

67

이것은 jQuery의 기본 jsonp 구현에 대한 알려진 제한 사항입니다. 아래 텍스트는 IBM DeveloperWorks 에서 가져온 것입니다.

JSONP는 매시업을 구축하기위한 매우 강력한 기술이지만, 안타깝게도 모든 교차 도메인 통신 요구를 해결할 수있는 방법은 아닙니다. 개발 리소스를 투입하기 전에 고려해야 할 몇 가지 단점이 있습니다. 무엇보다도 JSONP 호출에 대한 오류 처리가 없습니다. 동적 스크립트 삽입이 작동하면 호출됩니다. 그렇지 않으면 아무 일도 일어나지 않습니다. 조용히 실패합니다. 예를 들어, 서버에서 404 오류를 포착 할 수 없습니다. 요청을 취소하거나 다시 시작할 수도 없습니다. 그러나 적절한 시간을 기다린 후 시간 초과 할 수 있습니다. (향후 jQuery 버전에는 JSONP 요청에 대한 중단 기능이있을 수 있습니다.)

그러나 오류 처리를 지원 하는 GoogleCode 에서 사용할 수있는 jsonp 플러그인이 있습니다 . 시작하려면 코드를 다음과 같이 변경하십시오.

다운로드하거나 플러그인에 스크립트 참조를 추가 할 수 있습니다.

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

그런 다음 아래와 같이 ajax 호출을 수정합니다.

$(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);
        }
    });
});

José에 답 해주셔서 감사합니다! jQuery에서 네이티브 jsonp의 제한된 구현이 대신 $ .ajax를 선택한 이유였습니다. 그러나 문제는 $ .getJSON이 $ .ajax 주위의 래퍼가 아니라 dataType : jsonp라는 것 같습니다. 그 맞습니까?
Matijs 2009-06-16

오늘까지 시간이 없었습니다. 그러나 작동하지 않습니다. 오류가 발생하지만 그게 전부입니다. errorThrown이 정의되지 않은 오류가 무엇인지 모르겠습니다. 지금은 $ .ajax와 오류 메시지 부족을 고수하겠습니다. Javascript는 웹 페이지 상단에있는 추가 레이어입니다. Flickr가 다운되거나 오류 메시지를 던지는 경우, 우리는 당분간 함께 살아야합니다. :) 제안 해 주셔서 감사합니다.
Matijs

따라서 기본적으로 jsonp 플러그인을 사용하는 José의 제안이 올바르게 수행되면 작동합니다. 그러나 지금은 jQuery에 대한 기본 json 래퍼를 사용하겠습니다.
Matijs

jsonp의 오류 처리에 대한 내장 된 제한 사항으로 벽에 부딪혔을 때 이것은 저에게 훌륭하게 작동했습니다.
Jeremy Frey

7
이 팁으로 다른 개발자가 저장되었습니다. 감사!
chesterbr 2009

12

jQuery 1.4를 사용하는 경우 해결책 :

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

2
한마디로, 1.4를 고수하는 사람들에게 유효한 솔루션이지만 시간 제한 변수를 충분히 높게 설정하면 느린 웹 서비스에 문제가 없습니다. :). 예를 들어 1 초로 설정하면 오류 콜백이 트리거되고 1 초 후에도 여전히 호출이 가져와 성공 함수를 호출한다는 의미를 알 수 있습니다. 따라서 충분히 높게 설정하는 것을 명심하십시오
Sander

@Sander는 5 초의 타임 아웃으로 10 초 후에 응답을 받으면 성공 함수를 호출 할 수도 있습니다. .abort()제한 시간 후에 보류중인 jqXHR을 호출 하는 것이 더 좋은 방법 일 수 있습니다.
Matijs

8

이것은 jQuery의 "알려진"제한 사항 일 수 있습니다. 그러나 잘 문서화되지 않은 것 같습니다. 타임 아웃이 작동하지 않는 이유를 이해하기 위해 오늘 약 4 시간을 보냈습니다.

나는 jquery.jsonp 로 전환 했고 그것은 매력을 좋아했습니다. 감사합니다.


2

jQuery 1.5에서 해결 될 것 같습니다. 위의 코드를 시도했고 콜백을 받았습니다.

jQuery.ajax ()에 대한 오류 콜백 문서에 여전히 다음과 같은 메모가 있기 때문에 "있는 것 같습니다"라고 말합니다 .

참고 :이 핸들러는 교차 도메인 스크립트 및 JSONP 요청에 대해 호출되지 않습니다.


1

Jose Basilio의 답변에 언급 된 jquery-jsonp jQuery 플러그인 은 이제 GitHub 에서 찾을 수 있습니다 .

불행히도 문서는 다소 스파르타 적이므로 간단한 예를 제공했습니다.

    $.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"
        }
    });

중요 $ .jsonp () 호출에 callbackParameter를 포함하십시오. 그렇지 않으면 콜백 함수가 서비스 호출의 쿼리 문자열에 주입되지 않는 것으로 나타났습니다 (jquery-jsonp 버전 2.4.0 현재).

이 질문은 오래되었지만 JSONP를 사용한 오류 처리 문제는 여전히 '해결'되지 않았습니다. 이 질문이 Google 내에서 "jquery jsonp 오류 처리"에 대한 최상위 순위이므로이 업데이트가 다른 사용자에게 도움이되기를 바랍니다.


좋은 발견, 놀라운이 스레드는 ... 아직 3 년 살아있다
Matijs

1

스크립트의 onerror 이벤트를 수신하는 것은 어떻습니까? 나는이 문제가 있었고 스크립트 태그가 생성 된 jquery의 방법을 패치하여 해결했습니다. 다음은 흥미로운 코드입니다.

// 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;
}

이 솔루션에 대해 어떻게 생각하십니까? 호환성 문제를 일으킬 가능성이 있습니까?

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.