Почему этот обходной путь междоменного запроса работает?

В этой статье Джона Резига он имеет дело со списком слов размером со словарь слова с javascript, и он загружает контент через ajax из CDN.

Слова загружаются с символами новой строки, разделяющими слова. Затем он говорит, что перекрестный домен не работает:

Однако есть проблема: мы не можем загрузить наш словарь из CDN! Поскольку CDN находится на другом сервере (или в другом поддомене, как в данном случае), мы находимся во власти политики перекрестного происхождения браузера, запрещающей такие типы запросов. Однако не все потеряно — с помощью простой настройки файла словаря мы можем загружать его из разных доменов.

Во-первых, мы заменяем все концы в файле словаря пробелом. Во-вторых, мы оборачиваем всю строку оператором JSONP. Таким образом, окончательный результат выглядит примерно так:

dictLoaded('аааааааааааааааа... zyzzyvas zzz');

Это позволяет нам выполнять Ajax-запрос к файлу и заставить его работать так, как ожидалось, при этом все еще используя все кэширование и сжатие, предоставляемые браузером.

Итак, если я правильно понимаю, простое добавление его метода dictLoaded('original content') только к исходному контенту приводит к тому, что запрос ajax не завершается ошибкой.

Это (превращение его в функцию + параметр) действительно все, что нужно? и почему JSONP решает проблему ограничения междоменного доступа?


person Kristian    schedule 07.05.2012    source источник


Ответы (3)


теги <script> могут загружать любой файл JS из любого места (даже междоменного). Приятная вещь, которая приходит с ним, заключается в том, что код внутри этого скрипта также выполняется, следовательно, это метод обхода междоменных ограничений.

Проблема в том, что когда код выполняется, он выполняется в глобальной области видимости. поэтому, имея этот код:

var test = 'foo'

создаст переменную test в глобальной области видимости.

Чтобы смягчить это, вы используете заключение ответа в функцию. Это буква «P» в «JSONP», что означает «заполнение». Это заключает ваш ответ в вызов функции.

Итак, если ваш иностранный скрипт имеет:

myFunction({
    test : 'foo'
});

Он вызывает myFunction и передает объект с ключом test, который имеет значение foo. Принимающая функция будет выглядеть так:

function myFunction(data){
    //"data.test" is "foo"
}

Теперь мы успешно обошли междоменное ограничение. Необходимые основные части:

  • принимающая функция (которая может динамически создаваться и отбрасываться после использования)
  • «дополненный» ответ JSON
person Joseph    schedule 07.05.2012
comment
хороший ответ, спасибо. Поскольку тег сценария загружается вместе со страницей, как использование тега сценария заменяет традиционный вызов ajax, в котором вызов ajax инициируется некоторым событием? - person Kristian; 07.05.2012
comment
@Kristian AJAX ограничен политикой одного и того же источника, которая ограничивает междоменное взаимодействие, за исключением случаев использования общего доступа к ресурсам между источниками (CORS). CORS требует, чтобы сервер был настроен на разрешение запросов CORS. Однако JSONP этого не делает. Он просто загружает любой скрипт и выполняет его. Это похоже на чистую магию на стороне клиента — без вмешательства со стороны серверной части. - person Joseph; 07.05.2012
comment
Извините, наверное, я туманно сформулировал свой вопрос. перефразировано: не ограничен ли метод тега jsonp/script выполнением во время начальной загрузки страницы? тогда как запросы json от ajax происходят всякий раз, когда событие запускает его. Как мне согласовать эту разницу во времени? - person Kristian; 07.05.2012
comment
@Kristian yup, JSONP можно инициировать в любой момент времени. просто загрузите необходимые скрипты в формате JSONP. Они также асинхронны. - person Joseph; 07.05.2012

Это (превращение его в функцию + параметр) действительно все, что нужно?

да.

и почему это решает проблему ограничения междоменного доступа?

Вам следует прочитать о JSONP. Идея состоит в том, что теперь вы можете включать тег <script>, динамически указывающий на ресурс, вместо отправки запроса AJAX (что запрещено). И поскольку вы обернули содержимое именем функции, эта функция будет выполнена и передана в качестве аргумента объекта JSON. Итак, все, что вам осталось, это определить эту функцию.

person Darin Dimitrov    schedule 07.05.2012

Это из-за оператора JSONP, который он добавил.

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

Это работает через внедрение элементов скрипта.

JSONP имеет смысл только при использовании с элементом скрипта. Для каждого нового запроса JSONP браузер должен добавлять новый элемент или повторно использовать существующий. Первый вариант — добавление нового элемента сценария — выполняется с помощью динамической манипуляции с DOM и известен как внедрение элемента сценария. Элемент вводится в HTML DOM с URL-адресом желаемой конечной точки JSONP, установленным в качестве атрибута «src». Эта динамическая инъекция элемента скрипта обычно выполняется вспомогательной библиотекой javascript. jQuery и другие фреймворки имеют вспомогательные функции jsonp; есть и отдельные варианты.

Источник: http://en.wikipedia.org/wiki/JSONP

person Josh Mein    schedule 07.05.2012