开发者

jQuery get JSON response is empty

I'm trying to get a simple jQuery get JSON call to work. Neither my success handler non error handler seems to be getting called. Firebug also shows the data body as empty.

The server is a very basic bit of code running under web.py. I've tested the server by connecting to it with lynx and it downloads the json data OK.

Here's the jQuery:


$(document).ready(function() {
    $.ajax({
        url: 'http://localhost:8080/settings.json',
        cache: false,
        success: function(json){
    开发者_如何学C        alert('json success ' + json);
        },
        error: function(xhr, textStatus, errorThrown) {
            alert(xhr.statusText);
        }
    });
});

JSON data is:
{"netmask": "255.255.0.0", "ipaddress": "192.168.1.153"}


You can't make a request to another domain (that rule includes a different port) with an XmlHttpRequest, this is blocked by the same origin policy.

The result of trying to do this is an empty response, so you can't see the content. This is just a rule in place for security purposes...if you're connecting to the same host and port, it's a non-issue.


You can set up a reverse proxy in Apache that will make a remote data source look like it's coming from a local domain. I've written a blog post about how to do this:

http://senchabits.wordpress.com/2012/09/17/problem-accessing-json-data-from-a-local-data-source-is-not-permitted/


I've found a workaround to get an error callback with an empty response in cross domain requests.

In this example I'm using Zepto, a light-weight version of jQuery, but I assume that this works fine in jQuery too.

First of all, you must use these parameters to do a cross domain request:

$.ajax({
    url: url,
    type: 'GET',
    dataType: 'jsonp',
    contentType: 'application/x-javascript',
    crossDomain: true,
    success: function (data, status) { /* ... */ }
    error: function () { /* ... */ }
    // ...

Now, the $.ajax function internally use the $.ajaxJSONP for crossdomain requests. This is the original Zepto $.ajaxJSONP function:

  $.ajaxJSONP = function(options){
    var callbackName = 'jsonp' + (++jsonpID),
      script = document.createElement('script'),
      abort = function(){
        $(script).remove()
        if (callbackName in window) window[callbackName] = empty
        ajaxComplete('abort', xhr, options)
      },
      xhr = { abort: abort }, abortTimeout

    if (options.error) script.onerror = function() {
      xhr.abort()
      options.error()
    }

    window[callbackName] = function(data){
      clearTimeout(abortTimeout)
      $(script).remove()
      delete window[callbackName]
      ajaxSuccess(data, xhr, options)
    }

    serializeData(options)
    script.src = options.url.replace(/=\?/, '=' + callbackName)
    $('head').append(script)

    if (options.timeout > 0) abortTimeout = setTimeout(function(){
        xhr.abort()
        ajaxComplete('timeout', xhr, options)
      }, options.timeout)

    return xhr
  }

My workaround is very simple and consists on an interval called few times on the script.onload event handler, in order to verify that the callback function was called.

This is my version of the $.ajaxJSONP function:

$.ajaxJSONP = function(options){
    var called = false, // Flag to check that callback was called
        callbackName = 'jsonp' + (++jsonpID),
        script = document.createElement('script'),
        abort = function(){
            $(script).remove()
            if (callbackName in window) window[callbackName] = empty
            ajaxComplete('abort', xhr, options)
        },
        xhr = { abort: abort }, abortTimeout

    if (options.error) {
        script.onerror = function() {
            xhr.abort()
            options.error()
        };

        // IMPORTANT!!!
        script.onload = function () {
            var times = 0;

            var interval = setInterval(function () {
                // After 5 intervals, if the callback wasn't called, returns an error
                if (times++ == 5) {
                    clearInterval(interval);

                    if (!called) {
                        options.error();
                    }
                } else if (called) {
                    clearInterval(interval);
                }
            }, 100);
        };
    }

    window[callbackName] = function(data){
        // Setting the "called" flag to true
        called = true;
        clearTimeout(abortTimeout)
        $(script).remove()
        delete window[callbackName]
        ajaxSuccess(data, xhr, options)
    }

    serializeData(options)
    script.src = options.url.replace(/=\?/, '=' + callbackName)
    $('head').append(script)

    if (options.timeout > 0) abortTimeout = setTimeout(function(){
        xhr.abort()
        ajaxComplete('timeout', xhr, options)
    }, options.timeout)

    return xhr
}

Note: If you are interested in the server side behavior, please see the beginning of this tutorial: http://phonegap.com/2011/07/20/making-jsonp-calls-with-zepto-on-android-device/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜