web-dev-qa-db-ja.com

jQueryを使用してJSONajaxリクエストの404で関数をコールバックする方法は?

JSONで応答するAjaxリクエストを作成したいと思います。だから私はこのAjaxリクエストをしました:

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

このコードは正常に機能しますが、URLからHTTPコード404が送信されると、完全なコールバックであっても、コールバックは使用されません。調査の結果、dataTypeが 'json'であるため、404 returnがHTMLであり、JSON解析が失敗したためです。したがって、コールバックはありません。

404が発生したときにコールバック関数を呼び出すソリューションはありますか?

編集:完全なコールバックは呼び出さないで戻りは404です。404を使用したURLが必要な場合は、次のように呼び出すことができます: http://Twitter.com/status/user_timeline/jksqdlmjmsd.json?count=3&callback=jsonp1269278524295&_= 1269278536697 このURLに問題があります。

21
shingara
$.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');
    }
})
20
Dustin Laine

構成では、jQueryは jsonp を使用してデータを転送します。これは、スクリプト要素を動的に挿入し、URLを指定された値に設定することで機能します。サーバーから返されたデータはJavaScriptとして評価され、通常は提供されたコールバックを呼び出します。サーバーが404を返す場合、コンテンツは明らかにJavaScriptではなく、コールバックは呼び出されません。一部のブラウザは、このような状況で呼び出されるスクリプトタグのエラーハンドラをサポートしています。残念ながら、IEはこれをサポートしていません。エラーを検出する最良の方法は、タイムアウトに依存することです。

あなたの場合、追加のtimeoutオプションを指定する必要があります。これにより、コールバックが時間内に呼び出されなかった場合にエラーハンドラーが呼び出されます(これは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')
  }
});
9
Fabian Jakobs

Javascriptとjsonpを使用してTwitterAPIにアクセスする際のエラーを処理する場合は、リクエストにパラメーターsuppress_response_codesを含める必要があります。これにより、TwitterAPIからのすべての応答が200 OK応答で応答し、エラーが含まれます。次に、応答にerrorパラメーターが含まれているかどうかを確認する必要があります。

$.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);
    }
  }
});
4
Simon Gate

statusCode-オプションを使用する

$.ajax({
    url: 'http://my_url',
    dataType: "json",
    statusCode: {
        404: function() {
            alert("I could not find the information you requested.");
        }
    },
    success: function(data) {
      alert('success');
    },
    error: function(data) {
      alert('error');
    },
    complete: function(data) {
      alert('complete');
    }
})
3
Peter Rader

問題はdataTypeにあるのではなく、許可されていないクロスドメインリクエストにあると思いませんか?

以下のコードは、同じドメインからデータをリクエストする場合は期待どおりに機能し、クロスドメインリクエストを行う場合は機能しません。

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}
    );
}
2
newtover

HTTPステータスが404であっても、実際の本文は有効なJSONであることをご存知ですか?たとえば、 このリンク には次のJSONがあります。

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

そのため、通常のコールバック関数内でデータにerrorプロパティがあるかどうかを確認する必要があります。

[〜#〜] update [〜#〜]:どうやら、ページの実際のコンテンツは有効なJSONですが、ブラウザー(チェックインしました) Firefox)はそれを実行していません。おそらく404であるためです。jQueryはscript要素を追加する必要があるため(クロスドメインの問題のため)、そのJSONPラッパーは呼び出されず、結果として、どちらもあなたのコールバックではありません。

つまり、スクリプト要素を手動で追加し、事前定義されたコールバック関数が後で呼び出されたかどうかを確認せずに、これに対処する方法はないと思います。

1
janmoesen

同じ問題に直面し、 別の質問jQuery-JSONP(jQuery Plugin) 404エラーのキャッチをサポートしている、または次のように説明しているのを見ました: "ネットワーク障害または不正な形式のJSON応答の場合のエラー回復 "

そしてそれは完璧に動作します:)

JSONPを介してYouTubeビデオの詳細を取得するための私の(簡略化された)コードは次のとおりです。

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

dataTypeが「json」に設定されているからですか?その場合は、それをtextに変更して、JSONを自分で評価してみてください。

$.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');
    }
});
1
Matt Huggins

これが私がこれに対処する方法です。返されたデータを使用する前に、エラーがないか確認します。以下に示すのは、要件にさらに厳密に一致するように拡張できるサンプルにすぎません。これは、セッションのタイムアウトやその他のシナリオも考慮します...

私の最初の電話:

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

そして、2つのヘルパー関数:

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');
}
0
Glen Little

次の解決策は私にとってはうまく機能しています:)

$.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');
        }
    } 
});
0
Awan