2010-05-11 38 views
17

Tôi muốn hủy hoạt động .load() khi tải() không trở lại sau 5 giây. Nếu nó như vậy tôi hiển thị một thông báo lỗi như 'xin lỗi, không có hình ảnh được tải'.Làm thế nào để hủy bỏ một jquery.load()?

Những gì tôi đã là ...

... việc xử lý thời gian chờ:

jQuery.fn.idle = function(time, postFunction){ 
    var i = $(this); 
    i.queue(function(){ 
     setTimeout(function(){ 
      i.dequeue(); 
      postFunction(); 
     }, time); 
    }); 
    return $(this); 
}; 

... đang khởi tạo của thời gian chờ thông báo lỗi:

var hasImage = false; 

$('#errorMessage') 
    .idle(5000, function() { 

     if(!hasImage) { 
      // 1. cancel .load()    
      // 2. show error message 
     } 
    }); 

... các tải hình ảnh:

$('#myImage') 
    .attr('src', '/url/anypath/image.png') 
    .load(function(){ 
     hasImage = true; 
     // do something... 
     }); 

Điều duy nhất tôi không thể tìm ra là làm cách nào để hủy tải đang chạy() (nếu có thể).

Edit:

Một cách khác: Làm thế nào để ngăn chặn sự .load() phương pháp để gọi nó là chức năng gọi lại khi nó trở về?

Trả lời

10

Nếu bạn muốn bất kỳ xử lý tùy chỉnh nào như thế này, bạn chỉ đơn giản là không thể sử dụng hàm jQuery.load(). Bạn sẽ phải nâng cấp lên jQuery.ajax(), điều mà tôi khuyên bạn nên làm vì bạn có thể làm nhiều hơn thế với nó, đặc biệt nếu bạn cần bất kỳ loại xử lý lỗi nào, nó sẽ là cần thiết.

Sử dụng tùy chọn beforeSend cho jQuery.ajax và chụp xhr. Sau đó, bạn có thể tạo cuộc gọi lại có thể hủy xhr sau khi hết thời gian chờ của bạn và cuộc gọi lại khi cần thiết.

Mã này không được kiểm tra, nhưng sẽ giúp bạn bắt đầu.

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 
    ... 
    } 
}); 
+0

fullware, cảm ơn câu trả lời hữu ích của bạn! Có một điều nhỏ để sửa: Tôi đã phải thay thế dòng "beforeSend (xhr) {" với "beforeSend: function (xhr) {" – Dirk

2

Tôi nghĩ rằng điều đơn giản nhất cần làm là sử dụng trực tiếp $.ajax. Bằng cách đó bạn có thể bắt đầu một thời gian chờ, và từ thời gian chờ đặt một lá cờ mà người xử lý cuộc gọi ajax có thể kiểm tra. Thời gian chờ cũng có thể hiển thị một tin nhắn hoặc bất cứ điều gì.

+0

Xin chào, xin cảm ơn câu trả lời của bạn. Tôi đã có suy nghĩ tương tự, nhưng tôi không muốn phá vỡ các xử lý đóng gói tốt đẹp của jQuery ... – Dirk

+0

Vâng, '.load()' API là đồng bộ, và đó là điều đó. – Pointy

+0

hmm, tôi có thể phải thay đổi câu hỏi của mình thành: làm cách nào để ngăn chặn phương thức .load() gọi hàm gọi lại khi nó quay lại ... – Dirk

1

Tôi không nghĩ rằng bạn có thể đến đó từ đây - như @Pointy đã đề cập, bạn cần phải truy cập đối tượng XmlHttpRequest để bạn có thể truy cập phương thức .abort() trên đó. Đối với điều đó, bạn cần API jQuery .ajax() trả về đối tượng cho bạn.

Chặn khả năng hủy yêu cầu, một phương pháp khác cần xem xét là thêm kiến ​​thức về thời gian chờ vào hàm gọi lại. Bạn có thể làm điều này hai cách - đầu tiên:

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); 
     } 
    }); 

Và callback của bạn:

$('#myImage') 
    .attr('src', '/url/anypath/image.png') 
    .load(function(){ 
     if($(this).data("aborted")){ 
      $(this).removeData("aborted"); 
      return; 
     } 
     hasImage = true; 
     // do something... 
     }); 

Hoặc bạn có thể bỏ qua nhàn rỗi cho các chức năng đặc biệt này:

$('#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... 
     }); 

cách tiếp cận Không là lý tưởng, nhưng tôi không nghĩ rằng bạn có thể trực tiếp hủy tải như jQuery 1.4 - có thể là một yêu cầu tính năng tốt đẹp cho đội jQuery, mặc dù.

+1

+1 Nhưng '.attr ('src', '/url/anypath/image.png') 'ngay lập tức gửi yêu cầu HTTP để lấy hình ảnh, trước khi sự kiện tải được đăng ký. Bạn nên di chuyển 'attr()' đến cuối, sau 'load()'. –

2

Nếu bạn tải mã này sau khi JQuery đã được tải, bạn sẽ có thể gọi .load() với tham số hết giờ.

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; 
}; 

Không chắc chắn nếu bạn quan tâm đến việc ghi đè bất kỳ chức năng JQuery "chuẩn" nào, nhưng điều này sẽ cho phép bạn sử dụng .load() theo cách bạn mô tả.

0

$('#myImage').load(function(){...}) không phải là cuộc gọi hàm để tải hình ảnh, thực sự là viết tắt để ràng buộc gọi lại đến onloadevent.

Do đó, việc thêm tham số timeout vào .load()method như được đề xuất trong các câu trả lời khác sẽ không có hiệu lực.

Nó nghĩ hai lựa chọn của bạn là:

  1. Tiếp tục trên con đường bạn đang sau và làm điều gì đó như $('#myImage').attr('src', ''); để hủy tải hình ảnh sau khi nó lần ra, hoặc

  2. Tìm cách sử dụng $.ajax({ ... , timeout: 5000, ...}); để tải hình ảnh thay vì cho phép trình duyệt tự động thực hiện qua <img src="..."> thuộc tính.

3

câu hỏi thứ rephrased của bạn:
Làm thế nào để hủy cấp phát chức năng gọi lại, tạo ra bằng cách sử dụng phương pháp .load()?

Bạn có thể hủy bỏ tất cả callbacks jquery, bằng cách sử dụng tùy chọn 'hạt nhân' này:

$('#myImage').unbind('load'); 
+0

điều này không hoạt động khi phần tử dom được tạo tự động – PUG

0

Bạn chỉ có thể thiết lập một thời gian chờ trước khi tải hình ảnh cũng như thử nghiệm cho một lỗi tải.

function LoadImage(yourImage) { 

    var imageTimer = setTimeout(function() { 
     //image could not be loaded: 
     alert('image load timed out'); 
    }, 10000); //10 seconds 

    $(yourImage).load(function (response, status, xhr) { 
     if (imageTimer) { 

      if (status == 'error') { 
       //image could not be loaded: 
       alert('failed to load image'); 

      } else { 
       //image was loaded: 
       clearTimeout(imageTimer); 
       //display your image... 
      } 

     } 
    }); 

} 
Các vấn đề liên quan