jQuery getJSON работает локально, но не междоменно - PullRequest
12 голосов
/ 27 июля 2011

Я искал НАВСЕГДА и не могу найти однозначного ответа на мою проблему. Так и здесь. У меня есть файл JSON (я пошел в jsonlint для проверки, и он говорит, что это хорошо), который выглядит так (некоторая информация изменена):

[{
        "position":"1",
        "category":"A",
        "title":"Title to first story",
        "description":"The first story."
    },
    {
        "position":"2",
        "category":"B",
        "title":"Title to second story",
        "description":"The second story"
    },
    {
        "position":"3",
        "category":"B",
        "title":"Title to third story",
        "description":"The third story"
    }
]

Я использовал jQuery для анализа и размещения на html-странице с помощью этой функции:

$.getJSON('page.json', function(data) {
  var items = [];

  $.each(data.reponse, function(item, i) {
    items.push('<li id="' + i.position + '">' + i.title + ' - ' + i.description + '</li>');
  });

  $('<ul/>', {
    'class': 'my-new-list',
    html: items.join('')
  }).appendTo('body');
});

Работает отлично! Теперь возникает моя проблема, файл JSON не будет размещаться локально, а фактически будет размещаться в отдельном домене. Поэтому я изменил свой код следующим образом (после некоторого прочтения) в надежде заставить его работать:

$.getJSON('http://www.otherdomain.com/page.json?format=json&callback=?', function(data) {
  var items = [];

  $.each(data.reponse, function(item, i) {
    items.push('<li id="' + i.position + '">' + i.title + ' - ' + i.description + '</li>');
  });

  $('<ul/>', {
    'class': 'my-new-list',
    html: items.join('')
  }).appendTo('body');
});

Добавив строку «обратного вызова», я перестал получать ошибку «Не удалось загрузить ресурс». Однако ничего не происходит. Это похоже на то, что добавленной мной функции даже нет. Я пытался вынуть все это и добавить простое «предупреждение (данные)», но оно даже не сработало. Что я делаю неправильно? Большая проблема в том, что я на 100% ограничен только HTML и JavaScript для работы (не мой выбор). Спасибо за любую помощь!

EDIT Хорошо, у меня нет возможности для другого сервера динамически добавлять что-либо в файл json. Поэтому я изменил жестко закодировав функцию вокруг json (меньший образец):

storyData(
[{
        "position":"1",
        "category":"A",
        "title":"Title to first story",
        "description":"The first story."
    }
])

Теперь все работает! Спасибо за помощь!

Ответы [ 6 ]

15 голосов
/ 27 июля 2011

Вам нужно посмотреть на JSONP .

По сути, при попытке загрузить JSON из другого домена происходит сбой, поскольку существует граница домена, которую вы не можете пересечь. Чтобы избежать этого, вы должны PAD it (P в JSONP). Дополнение к нему - это, по сути, завершение его в вызове функции (где имя функции находится на вашем клиенте.) Например, «нормальный» ответ JSON (например, getjson.php):

{foo:'bar'}

JSON с обратным вызовом parseJSON становится (скажем, например, getjson.php? Callback = parseJSON):

parseJSON({foo:'bar'})

Обратите внимание, как значение, указанное в callback , становится именем функции, в которую теперь включен ваш ответ JSON.

Тогда ваш клиент захочет передать его в parseJSON, функцию, которая существует на вашем клиенте (которую вы определили). jQuery (и другие библиотеки) пытаются позаботиться об этом за вас, сгенерировав некоторую «случайную» функцию, а затем отправив ответ обратно через ваш оригинальный обратный вызов (все это делается под капотом).

Если у вас есть контроль над страницей сервера, генерирующей JSON, реализуйте метод обратного вызова, чтобы вы могли указать, как JSON должен быть упакован, чтобы вы могли работать с ним на своем конце. (Это необходимо, только если вы имеете дело с данными из домена, отличного от страницы, на которой в данный момент находится клиент).


UPDATE

Чтобы в основном решить проблему, с которой вы столкнулись, вам нужно найти способ передать информацию JSON в вызов JSONP. Не зная, на каком языке находится ваш "page.json", вот логика псевдокода, которую он должен содержать:

if GET_VARIABLE("callback") is supplied

  print GET_VARIABLE("callback") and an open parenthesis
  print normal JSON data
  print closing parenthesis

else

  print normal JSON data

end if

Если вы решили жестко закодировать имя функции вместо того, чтобы разрешить указывать ее в URL как «обратный вызов», вам нужно запомнить это. В следующем примере давайте представим, что мы назвали его MyJSONPCallback

Теперь в вашем клиентском коде вы можете использовать его заранее:

$.ajax({
  url: 'http://anotherdomain.com/page.json?format=json',
  dataType: 'json',
  jsonpCallback: 'MyJSONPCallback', // specify the callback name if you're hard-coding it
  success: function(data){
    // we make a successful JSONP call!
  }
});
2 голосов
/ 25 мая 2012

Для тех, кто использует MVC ActionResult для генерации JSONP, ASP.NET MVC не поставляется с поддержкой JSONP «из коробки», но его легко добавить с помощью:

http://nikcodes.com/2012/02/29/an-asp-net-mvc-jsonp-actionresult

0 голосов
/ 16 декабря 2015

Ответ Брэда Кристи помог мне быстро заставить мой код работать. Я создаю новую запись здесь, так как она немного проще, чем другие решения.

Ниже приведен код, с которого я запускаю http://localhost:5000 -

(function() {
        var api = "http://www.localhost:3000/auget_from_server?format=json";
        var request = $.getJSON( api, {
            secret : 'secret', 
            appId : 'app', 
            emailId : 'abc@gmail.com',
            async: false,
            dataType : 'json',
          },
          function(data, result){
            $("div.some_div").append(JSON.stringify(data));
          });

        request.complete(function(d, status){
            console.log('Complete the request and got the data - ' + JSON.stringify(d) + '/' + status, filename);
        });

        request.error(function(err){
            console.log('Error happened - ', filename);
            console.log(err);
        });

        request.success(function( data, status, jqXHR ) {
            $("div.some_div").append(data);
        });


        })();

Из местоположения в http://localhost:3000/auget_from_server, Я возвращаю следующий JSON в ответ (эта часть относится только к метеору, но он также будет работать и для неметеорных серверов) -

this.response.writeHead('200', {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'});
this.response.end(JSON.stringify([{'works_or_not' : 'works', 'name' : 'akaushik', 'application' : 'Qoll', 'message' : 'hello from server', 'currentTime' : dt+''}]));

Это печатает следующее в журналах -

Complete the request and got the data - {"readyState":4,"responseText":"[{\"works_or_not\":\"works\",\"name\":\"akaushik\",\"application\":\"Qoll\",\"message\":\"hello from server\",\"currentTime\":\"Tue Dec 15 2015 23:59:14 GMT-0500 (EST)\"}]","responseJSON":[{"works_or_not":"works","name":"akaushik","application":"Qoll","message":"hello from server","currentTime":"Tue Dec 15 2015 23:59:14 GMT-0500 (EST)"}],"status":200,"statusText":"OK"}/success
0 голосов
/ 27 июля 2011

См. Эту статью - вы должны предоставить действительный объект javascript, заключенный в функцию.

http://en.wikipedia.org/wiki/JSONP

Вы хотели бы вернуть что-то вроде:

parseResponse({"Name": "Cheeso", "Id" : 1823, "Rank": 7})

Но ваш метод на стороне сервера должен знать, чтобы вернуть это, а не только JSON внутри. Все, что делает jQuery, - это автоматически генерирует имя функции (? в параметре callback) и затем выдает «функцию», возвращаемую с сервера. Сервер создает вызов функции с JSON, содержащимся внутри.

0 голосов
/ 27 июля 2011

Я не углублялся в эту проблему, но я полагаю, что ваша проблема связана с той же политикой домена ... вы можете рассмотреть это, хотя: http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/

0 голосов
/ 27 июля 2011

Браузеры не допускают, чтобы это работало в качестве меры безопасности. Вы можете проверить JSONP как способ обойти это, хотя это ОГРОМНАЯ угроза безопасности, поскольку она основана на запуске javascript, предоставленного доменом, из которого вы получаете текст JSON.

...