Лучшая практика для jQuery JSONP
В документах для $.getJSON
и $.ajax
в разделе jsonp указано, что вы можете задать имя функции обратного вызова явно с помощью свойства конфигурации jsonpCallback
. Итак, если вы хотите, чтобы JsonWrapping(...)
была функцией, которую jquery ожидает внутри ответа jsonp, вы можете связать вещи следующим образом:
$.ajax({
url: 'http://blah.com/blah.json',
dataType: 'jsonp',
cache: true,
jsonpCallback: 'JsonWrapping'
})
.done(function(r) {
status.text('It worked.');
})
.fail(function (a, b, c) {
status.text('It failed.');
});
В приведенном выше примере ожидаемая функция обратного вызова внутри ответа jsonp теперь имеет значение JsonWrapping()
, которое jQuery выдаст для вас, ответит вызовом .done()
выше и очистит после себя — намного чище, чем жесткое кодирование JsonWrapping
на странице.
Опасности жесткого кодирования и предложений по именованию
Важно учитывать, что если вы планируете иметь много вызовов jsonp на одной странице, а ваши функции переноса jsonp жестко запрограммированы в файлах jsonp, вы должны, по крайней мере, изменить свою функцию переноса чем-то, например, именем файла. В противном случае вы создадите проблему асинхронности. Например, предположим, что у вас есть этот код:
function jsonp(url) {
return $.ajax({
url: url,
dataType: 'jsonp'
cache: true,
jsonpCallback: 'JsonWrapping'
});
}
jsonp('http://cdn.mine/one.jsonp')
.done(...);
jsonp('http://cdn.mine/two.jsonp')
.done(...);
Один из этих вызовов jsonp завершится раньше другого — невозможно узнать какой — и jQuery находится в невозможной ситуации, когда он не может знать, какой .done()
вызывать для какого ответа. В результате вы получите некоторые загрузки страниц там, где они вызываются правильно, и некоторые страницы, где данные перекрещиваются. Решение состоит в том, чтобы изменить что-то вроде имени файла, например:
function jsonp(url, wrapper) {
return $.ajax({
url: url,
dataType: 'jsonp'
cache: true,
jsonpCallback: wrapper
});
}
jsonp('http://cdn.mine/one.jsonp', 'one')
.done(...);
jsonp('http://cdn.mine/two.jsonp', 'two')
.done(...);
Таким образом, ответ от two.jsonp должен выглядеть так:
two({...json object here...})
Как это работает
Вызов в начале этого ответа заставит jQuery запросить URL-адрес через GET следующим образом:
http://blah.com/blah.json?callback=JsonWrapping
И ожидайте этого в качестве ответа:
JsonWrapping({...object here...})
Я включил cache: true
выше, потому что это на CDN, и поэтому, по-видимому, не должно меняться очень часто. Если вы опустите cache: true
, jQuery вставит второй параметр строки запроса, предназначенный для очистки кеша, например:
http://blah.com/blah.json?callback=JsonWrapping&_=1365175172440
Что может испортить суть CDN. Цель второго параметра строки запроса — гарантировать, что данные не загружаются из кеша браузера, и, когда они попадают на сервер (в данном случае CDN), строка запроса уникальна, что означает, что она также разрушает свой кеш.
Вне вашего сценария, когда вы используете CDN, существуют ситуации, когда функциональность jQuery по умолчанию желательна: например, когда вы хотите имитировать функциональность POST для другого домена, не нарушая политику того же происхождения, jsonp с этой функцией очистки кеша может сделать это для вас.
Если сервер, с которым вы разговариваете, ожидает в строке запроса что-то отличное от «обратного вызова» для указания имени функции обратного вызова в ответе, вы можете использовать свойство конфигурации jsonp
— например, jsonp: 'myname'
даст вам:
http://blah.com/blah.json?myname=JsonWrapping
person
Chris Moschini
schedule
03.05.2012