Я нашел обходной путь для получения обратного вызова с ошибкой с пустым ответом в междоменных запросах.
В этом примере я использую Zepto, облегченную версию jQuery, но я предполагаю, чтоэто хорошо работает и в jQuery.
Прежде всего, вы должны использовать следующие параметры для выполнения междоменного запроса:
$.ajax({
url: url,
type: 'GET',
dataType: 'jsonp',
contentType: 'application/x-javascript',
crossDomain: true,
success: function (data, status) { /* ... */ }
error: function () { /* ... */ }
// ...
Теперь $. ajax Функция внутренне использует $. ajaxJSONP для междоменных запросов.Это оригинальная функция Zepto $. AjaxJSONP :
$.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
}
Мой обходной путь очень прост и состоит из интервала, вызываемого несколько раз в обработчике события script.onload, чтобы проверитьчто была вызвана функция обратного вызова.
Это моя версия функции $. ajaxJSONP :
$.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
}
Примечание. Если вас интересует поведение на стороне сервераПожалуйста, смотрите начало этого урока: http://phonegap.com/2011/07/20/making-jsonp-calls-with-zepto-on-android-device/