Я хотел бы отменить .load () операция, когда загрузка () не возвращается через 5 секунд. Если это так, я показываю сообщение об ошибке как 'жаль, никакое загруженное изображение'.
То, что я имею...
... обработка тайм-аута:
jQuery.fn.idle = function(time, postFunction){
var i = $(this);
i.queue(function(){
setTimeout(function(){
i.dequeue();
postFunction();
}, time);
});
return $(this);
};
... инициализация тайм-аута сообщения об ошибке:
var hasImage = false;
$('#errorMessage')
.idle(5000, function() {
if(!hasImage) {
// 1. cancel .load()
// 2. show error message
}
});
... загрузка изображения:
$('#myImage')
.attr('src', '/url/anypath/image.png')
.load(function(){
hasImage = true;
// do something...
});
Единственная вещь, которую я не мог выяснить, состоит в том, как отменить рабочую загрузку () (если это возможно).
Править:
Иначе: Как я предотвращаю .load () метод для вызова, это - функция обратного вызова, когда он возвращается?
Если вам нужна какая-либо пользовательская обработка, подобная этой, вы просто не можете использовать функцию jQuery.load(). Вам придется перейти на jQuery.ajax(), которую я рекомендую в любом случае, поскольку с ней вы можете сделать гораздо больше, особенно если вам нужна какая-либо обработка ошибок, это будет необходимо.
Используйте опцию beforeSend для jQuery.ajax и перехватывайте xhr. Затем вы можете создать обратный вызов, который может отменить xhr после вашего таймаута, и обратные вызовы по мере необходимости.
Этот код не тестировался, но должен помочь вам начать.
var enableCallbacks = true;
var timeout = null;
jQuery.ajax({
....
beforeSend: function(xhr) {
timeout = setTimeout(function() {
xhr.abort();
enableCallbacks = false;
// Handle the timeout
...
}, 5000);
},
error: function(xhr, textStatus, errorThrown) {
clearTimeout(timeout);
if (!enableCallbacks) return;
// Handle other (non-timeout) errors
},
success: function(data, textStatus) {
clearTimeout(timeout);
if (!enableCallbacks) return;
// Handle the result
...
}
});
Я думаю, что проще всего было бы напрямую использовать $. Ajax
. Таким образом, вы можете запустить тайм-аут, а из тайм-аута установить флаг, который может проверить обработчик вызова ajax. По таймауту также может отображаться сообщение или что-то еще.
Я не думаю, что вы можете добраться отсюда - как упоминал @Pointy, вам нужно добраться до объекта XmlHttpRequest, чтобы вы могли получить доступ к .abort ()
на нем. Для этого вам понадобится jQuery API .ajax ()
, который возвращает вам объект.
За исключением возможности прервать запрос, следует рассмотреть еще один способ - добавить информацию о тайм-ауте в функцию обратного вызова. Вы можете сделать это двумя способами - первый:
var hasImage = false;
$('#errorMessage')
.idle(5000, function() {
if(!hasImage) {
// 1. cancel .load()
// 2. show error message
// 3. Add an aborted flag onto the element(s)
$('#myImage').data("aborted", true);
}
});
И ваш обратный вызов:
$('#myImage')
.attr('src', '/url/anypath/image.png')
.load(function(){
if($(this).data("aborted")){
$(this).removeData("aborted");
return;
}
hasImage = true;
// do something...
});
Или вы можете обойти простоя для этой конкретной функции:
$('#myImage')
.attr('src', '/url/anypath/image.png')
.data("start", (new Date()).getTime())
.load(function(){
var start = $(this).data("start");
$(this).removeData("start");
if(((new Date()).getTime() - start) > 5000)
return;
hasImage = true;
// do something...
});
Ни один из подходов не идеален, но я не думаю, что вы можете напрямую отменить загрузку, поскольку jQuery 1.4 - тем не менее, это может быть хорошим запросом на добавление функций для команды jQuery.
Если вы загрузите этот код после загрузки JQuery, вы сможете вызвать .load () с параметром тайм-аута.
jQuery.fn.load = function( url, params, callback, timeout ) {
if ( typeof url !== "string" ) {
return _load.call( this, url );
// Don't do a request if no elements are being requested
} else if ( !this.length ) {
return this;
}
var off = url.indexOf(" ");
if ( off >= 0 ) {
var selector = url.slice(off, url.length);
url = url.slice(0, off);
}
// Default to a GET request
var type = "GET";
// If the second parameter was provided
if ( params ) {
// If it's a function
if ( jQuery.isFunction( params ) ) {
if( callback && typeof callback === "number"){
timeout = callback;
callback = params;
params = null;
}else{
// We assume that it's the callback
callback = params;
params = null;
timeout = 0;
}
// Otherwise, build a param string
} else if( typeof params === "number"){
timeout = params;
callback = null;
params = null;
}else if ( typeof params === "object" ) {
params = jQuery.param( params, jQuery.ajaxSettings.traditional );
type = "POST";
if( callback && typeof callback === "number"){
timeout = callback;
callback = null;
}else if(! timeout){
timeout = 0;
}
}
}
var self = this;
// Request the remote document
jQuery.ajax({
url: url,
type: type,
dataType: "html",
data: params,
timeout: timeout,
complete: function( res, status ) {
// If successful, inject the HTML into all the matched elements
if ( status === "success" || status === "notmodified" ) {
// See if a selector was specified
self.html( selector ?
// Create a dummy div to hold the results
jQuery("<div />")
// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(rscript, ""))
// Locate the specified elements
.find(selector) :
// If not, just inject the full result
res.responseText );
}
if ( callback ) {
self.each( callback, [res.responseText, status, res] );
}
}
});
return this;
};
Не уверен, что вас интересует перезапись каких-либо «стандартных» функций JQuery, но это позволит вам использовать .load () так, как вы описали.