Статьи

Начало работы с JSON-P

Во время учебы в колледже я использовал объекты XMLHttpRequest и их эквиваленты в мире Microsoft для выполнения вызовов Ajax, которые были отправлены на URL в том же домене. Но с появлением веб-сервисов и созданием множества гибридных приложений вызовы Ajax не ограничиваются одним доменом, а пересекаются с различными доменами. Когда происходит такое сокращение границ домена, выполнение вызова Ajax с использованием XMLHttpRequest завершится неудачей из-за мер безопасности, реализованных браузерами. Вот тогда и возникла идея JSON-P, т.е. JSON с Padding.

В этой статье я процитирую из разных источников информацию о JSON-P, а затем продолжу и буду реализовывать примеры, которые вызывают API-интерфейс Stackoverflow для получения неотвеченных вопросов с тегом «jsonp».

  1. Что такое JSON-P?
  2. Простой пример для JSON-P
  3. Доступ к API Stackoverflow с использованием JSON-P


Что такое JSONP?

Я не собираюсь пересматривать его определение. Вместо этого я приведу его определение из разных источников:

С головы первого HTML5:

JSONP — это способ получения объектов JSON с помощью scriptтега. Это также способ извлечения данных (опять же, в форме объектов JSON), который позволяет избежать проблем безопасности того же происхождения, которые мы видели в XMLHttpRequest. JSONP — это данные JSON, заключенные в JavaScript; как правило, вызов функции.

С http://json-p.org/

Одним из таких механизмов, который может запрашивать междоменный контент, является scriptтег. В декабре 2005 года Боб Ипполито официально предложил JSONP (позже названный JSON-P или JSON-with-padding) как способ использовать это свойство scriptтегов, чтобы иметь возможность запрашивать данные в формате JSON между доменами. JSON-P работает, создавая scriptэлемент (либо в разметке HTML, либо вставляя его в DOM через JavaScript), который запрашивает расположение удаленной службы данных. Ответ (загруженный контент «JavaScript») — это имя функции, предварительно определенной на запрашивающей веб-странице, причем передаваемый ей параметр является запрашиваемыми данными JSON. Когда сценарий выполняется, функция вызывается и передает данные JSON, позволяя запрашивающей странице получать и обрабатывать данные.

Из Википедии: http://en.wikipedia.org/wiki/JSONP

JSONP или «JSON with padding» — это метод связи, используемый в программах JavaScript, которые работают в веб-браузерах. Он предоставляет метод для запроса данных с сервера в другом домене, что запрещено обычными веб-браузерами из-за одной и той же политики происхождения.

Подводя итог, можно сказать, что JSONP — это метод связи, позволяющий извлекать данные из некоторого URL-адреса, а затем использовать scriptтег для установления связи и JavaScript для обновления HTML.
Было много вопросов о том, насколько безопасен JSONP, но я не хочу вдаваться в эти обсуждения, так как это не основной мотив этого поста.

Теперь, позвольте мне показать JSONP в действии на простом примере.

Простой пример для JSONP

Для простого примера я воспользуюсь некоторыми ресурсами из главы о JSONP в книге Head First HTML5. Я собираюсь сделать вызов JSONP для ресурса Javascript, который, в свою очередь, вызывает функцию обратного вызова, объявленную в моем источнике Javascript.

Давайте посмотрим на источник HTML:

<html>
  <head>
    <title></title>
    <meta charset="UTF-8">
    <script src="simple.js"></script>
  </head>
  <body>
    <h1>JSONP Simple Demo</h1>
    <!-- we will update the data here -->
    <div id="jsonp"></div>
  </body>
</html>

Интересная вещь происходит в коде JavaScript.

//simple.js
window.onload = function(){
  //Get the head element.
  var head = document.getElementsByTagName("head")[0];
  
  //url for the javascript resource for JSONP call.
  var url = "http://wickedlysmart.com/hfhtml5/chapter6/dog3.js";
  
  //Appending the script tag to the head element.
  //This triggers a JSONP call to get the data.
  var scriptTag = document.createElement("script");
  scriptTag.setAttribute("src",url);
  head.appendChild(scriptTag);
}

//Method invoked by JSONP
function animalSays(animal){
  var div = document.getElementById("jsonp");
  div.innerHTML = animal.type +" says "+ animal.sound;
}

«Http://wickedlysmart.com/hfhtml5/chapter6/dog3.js» содержит:

var animal = { "type": "dog", "sound": "woof" };
animalSays(animal);

Приведенный выше код JavaScript:
1. Создает объект JSON
2. Вызывает обратный вызов, передавая объект JSON.

Теперь вопрос в том, где animalSaysобъявлен метод? Если вы внимательно посмотрели на simple.js, вы можете увидеть, что метод animalSaysбыл объявлен. Когда JavaScript в приведенном выше URL-адресе запрашивается с использованием техники JSONP путем динамического добавления script, в браузере выполняется javascript, который содержит определение animalSaysметода.

animalSaysМетод возвращает объект JSON , а затем заполняет HTML с данными в объекте JSON.

Давайте посмотрим на лучший пример.

Доступ к API Stackoverflow с использованием JSONP

Подробную информацию о API Stackoverflow для вопросов без ответов можно найти здесь . URL-адрес для доступа к оставшимся без ответа вопросам с тегом «jsonp»: https://api.stackexchange.com/2.1/questions/unanseded?order=desc&sort=activity&tagged=jsonp&site=stackoverflow

Приведенный выше URL возвращает некоторые данные JSON, но как это помогает в использовании JSONP? Можно добавить другой параметр к указанному выше URL-адресу, называемый «обратный вызов», который будет принимать имя метода JavaScript, который будет вызываться после загрузки URL-адреса scriptтегом.

Давайте посмотрим на код HTML:

//sflow.html
<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script src="sflow.js"></script>
  </head>
  <body>
    <div>Unanswered questions tagged 'jsonp'</div>
    <!-- placeholder for updating the questions -->
    <div id="questions">
    </div>
  </body>
</html>

Код JavaScript состоит из 2 частей:

  • Часть 1: Загрузка URL, который содержит данные и вызов функции.
window.onload = function() {
  var head = document.getElementsByTagName("head")[0];
  var script = document.createElement("script");
  
  var url = "https://api.stackexchange.com/2.1/questions/unanswered?" +
          "order=desc" +
          "&sort=activity" +
          "&tagged=jsonp" +
          "&site=stackoverflow" +
          "&callback=listUnansweredQuestions";
  //The URL is loaded by including it in the script tag and adding to the DOM.
  script.setAttribute("src", url);
  head.appendChild(script);
}
  • Часть 2: Определение обратного вызова, который получает данные, а затем обновляет HTML
function listUnansweredQuestions(questions) {
  var div = document.getElementById("questions");
  var ul = document.createElement("ul");
  div.appendChild(ul);
  for (var i = 0; i < questions.items.length; i++) {
    var question = questions.items[i];
    var li = document.createElement("li");
    li.innerHTML = "<a href="+question.link+">"+question.title+"</a>";
    ul.appendChild(li);
  }
}

Полный код Javascript будет:

//sflow.js
window.onload = function() {
  var head = document.getElementsByTagName("head")[0];
  var script = document.createElement("script");

  var url = "https://api.stackexchange.com/2.1/questions/unanswered?" +
          "order=desc" +
          "&sort=activity" +
          "&tagged=jsonp" +
          "&site=stackoverflow" +
          "&callback=listUnansweredQuestions";

  script.setAttribute("src", url);
  head.appendChild(script);
}

function listUnansweredQuestions(questions) {
  var div = document.getElementById("questions");
  var ul = document.createElement("ul");
  div.appendChild(ul);
  for (var i = 0; i < questions.items.length; i++) {
    var question = questions.items[i];
    var li = document.createElement("li");
    li.innerHTML = "<a href="+question.link+">"+question.title+"</a>";
    ul.appendChild(li);
  }
}

Выход для выше HTML и Javascript будет: Если у вас есть какие — либо вопросы , в под управлением любой из образца кода , показанного в посте выше, пожалуйста, свяжитесь через комментарии ниже.
JSONP_result