ยกเลิกคำขอ Ajax โดยใช้ jQuery


1827

การใช้ jQuery ฉันจะยกเลิก / ยกเลิกคำขอ Ajaxที่ฉันยังไม่ได้รับการตอบกลับได้อย่างไร


2
บางทีฉันอาจจะเข้าใจผิดคำถาม แต่คุณใช้$.ajaxStopไม่ได้เหรอ?
Luke Madhanga

17
@LukeMadhanga; ฉันคิดว่าajaxStopตรวจพบเฉพาะเมื่อคำขอ AJAX ทั้งหมดเสร็จสมบูรณ์ แต่จะไม่หยุดคำขอ จากประสบการณ์ของฉันคุณจะใช้มันแบบนี้: $(document).ajaxStop(function(){alert("All done")}). การใช้.abort()เป็นตัวเลือกที่ดีที่สุด
TheCarver

คำตอบ:


1744

เมธอด jQuery Ajax ส่วนใหญ่ส่งคืนออบเจ็กต์ XMLHttpRequest (หรือเทียบเท่า) ดังนั้นคุณจึงสามารถใช้งานabort()ได้

ดูเอกสารประกอบ:

var xhr = $.ajax({
    type: "POST",
    url: "some.php",
    data: "name=John&location=Boston",
    success: function(msg){
       alert( "Data Saved: " + msg );
    }
});

//kill the request
xhr.abort()

ปรับปรุง: ณ jQuery 1.5 วัตถุที่ส่งคืนเป็น wrapper สำหรับวัตถุ XMLHttpRequest ดั้งเดิมที่เรียกว่า jqXHR วัตถุนี้ดูเหมือนจะเปิดเผยคุณสมบัติและวิธีการดั้งเดิมทั้งหมดดังนั้นตัวอย่างด้านบนจึงยังใช้งานได้ โปรดดูเอกสาร jqXHR Object (jQuery API)

ปรับปรุง 2: ณ jQuery 3 ตอนนี้วิธี ajax ส่งคืนสัญญาด้วยวิธีพิเศษ (เช่นยกเลิก) ดังนั้นโค้ดข้างต้นยังคงใช้งานได้แม้ว่าวัตถุที่ส่งคืนจะไม่ได้xhrอีกต่อไป ดูบล็อก 3.0 ที่นี่

อัปเดต 3 : xhr.abort()ยังคงทำงานกับ jQuery 3.x อย่าถือว่าการอัพเดท 2นั้นถูกต้อง ข้อมูลเพิ่มเติมเกี่ยวกับพื้นที่เก็บข้อมูล jQuery Github


12
มันเหมือนกับการคลิกปุ่ม 'หยุด' บนเบราว์เซอร์ของคุณ มันยกเลิกการร้องขอ จากนั้นคุณสามารถนำวัตถุ XHR เดียวกันมาใช้ซ้ำสำหรับคำขออื่น
30715 meouw

65
@brad แต่น่าเสียดายที่abortไม่ได้ปิดการเชื่อมต่อที่สร้างไว้กับเซิร์ฟเวอร์ดังนั้นsuccessจะยังคงถูกเรียกใช้ นี่เป็นปัญหาอย่างมากสำหรับการใช้งาน Comet ที่มีการลงคะแนนแบบยาว
pepkin88

6
@ErvWalter คุณสามารถส่งคำขออื่นที่ยกเลิกคำขอก่อนหน้านี้
ซาด Saeeduddin

8
ในการทดสอบของฉันคำขอจะถูกยกเลิกที่เบราว์เซอร์ แต่มีการเรียกใช้เมธอด. () ด้วย jqXHR, สถานะ = 0, และ jqXHR, statusMessage = "ยกเลิก"
BJ Safdie

9
.abort()ยังคงใช้ได้สำหรับฉันใน jQuery 3.2.1 ความคิดเห็นนี้ในปัญหา github ที่เกี่ยวข้องโดยสมาชิกในทีมหลักของ jQuery ดูเหมือนจะบอกเป็นนัยว่าคำตอบนี้ไม่ถูกต้องและ.abort() ไม่ได้ถูกลบออก
เปิดรับ

117

คุณไม่สามารถเรียกคืนการร้องขอ แต่คุณสามารถตั้งค่าการหมดเวลาหลังจากนั้นการตอบสนองจะถูกละเว้น ดูหน้านี้สำหรับตัวเลือก jquery AJAX เราเชื่อว่าการโทรกลับข้อผิดพลาดของคุณจะถูกเรียกหากเกินกำหนดระยะเวลาการหมดเวลา มีการหมดเวลาเริ่มต้นในทุกคำขอ AJAX

นอกจากนี้คุณยังสามารถใช้วิธีการยกเลิก ()กับวัตถุที่ร้องขอ แต่ในขณะที่มันจะทำให้ลูกค้าหยุดฟังเหตุการณ์มันอาจจะไม่หยุดเซิร์ฟเวอร์จากการประมวลผล


74

มันเป็นคำขอแบบอะซิงโครนัสซึ่งหมายความว่าเมื่อส่งออกแล้ว

ในกรณีที่เซิร์ฟเวอร์ของคุณกำลังเริ่มการดำเนินการที่แพงมากเนื่องจากคำขอ AJAX สิ่งที่ดีที่สุดที่คุณทำได้คือเปิดเซิร์ฟเวอร์เพื่อฟังคำขอยกเลิกและส่งคำขอ AJAX แยกต่างหากเพื่อแจ้งให้เซิร์ฟเวอร์หยุดสิ่งที่กำลังทำอยู่

มิฉะนั้นเพียงละเว้นการตอบกลับ AJAX


48
ในบริบทนี้อะซิงโครนัสก็หมายความว่าคำขอไม่ได้ขัดขวางการไหลของสคริปต์ ขณะนี้เบราว์เซอร์มีความสามารถในการยกเลิกคำขอก่อนกำหนดก่อนที่คำขอจะเสร็จสมบูรณ์
ElephantHunter

4
เราจะส่งคำร้องขอยกเลิกไปยังเซิร์ฟเวอร์ได้อย่างไร ฉันไม่เข้าใจว่าเซิร์ฟเวอร์จะทราบได้อย่างไรว่าคำขอใดที่จะหยุดการประมวลผล คุณยกตัวอย่างได้ไหม ขอบคุณ.
Lucky Soni

3
@ LuckySoni, Elephanthunter กำลังพูดถึงฝั่งไคลเอ็นต์เท่านั้น เซิร์ฟเวอร์จะไม่ได้รับผลกระทบจากคำขอ .
abort

4
@Kloar หากการร้องขอยังไม่ได้รับจากเซิร์ฟเวอร์ (f.ex. การร้องขอ multpart ขนาดใหญ่) ไคลเอ็นต์อาจปิดซ็อกเก็ตและเซิร์ฟเวอร์จะได้รับผลกระทบ
สีขาว

4
PHP ตรวจสอบคำขอที่ถูกยกเลิกโดยอัตโนมัติและยกเลิกโดยอัตโนมัติเช่นกัน ดูphp.net/manual/en/function.ignore-user-abort.php
hanshenrik

68

บันทึกการโทรที่คุณทำไว้ในอาร์เรย์จากนั้นโทร xhr.abort () ในแต่ละรายการ

ถ้ำขนาดใหญ่: คุณสามารถยกเลิกการร้องขอ แต่นั่นเป็นเพียงฝั่งลูกค้า ฝั่งเซิร์ฟเวอร์ยังคงสามารถประมวลผลคำขอได้ หากคุณกำลังใช้บางอย่างเช่น PHP หรือ ASP กับข้อมูลเซสชันข้อมูลเซสชันจะถูกล็อคจนกว่า ajax จะเสร็จสิ้น ดังนั้นเพื่อให้ผู้ใช้สามารถเรียกดูเว็บไซต์ต่อไปได้คุณต้องโทรsession_write_close () นี่เป็นการบันทึกเซสชันและปลดล็อกเพื่อให้หน้าอื่น ๆ ที่รอดำเนินการต่อไปจะดำเนินการต่อไป หากไม่มีสิ่งนี้หลายหน้าสามารถรอให้การล็อกถูกลบ


เนื่องจากคุณยกเลิกรายการก่อนหน้านี้เสมอคุณทำเช่นนั้นไม่ได้ใช่ไหม (และไม่จำเป็นต้องใช้อาร์เรย์)
nonopolarity

60

คำขอ AJAX อาจไม่สมบูรณ์ตามลำดับที่เริ่มต้น แทนที่จะยกเลิกคุณสามารถเลือกละเว้นการตอบกลับ AJAX ทั้งหมดยกเว้นการตอบกลับล่าสุด:

  • สร้างเคาน์เตอร์
  • เพิ่มตัวนับเมื่อคุณเริ่มต้นคำขอ AJAX
  • ใช้ค่าปัจจุบันของตัวนับเพื่อ "ประทับ" คำขอ
  • ในการติดต่อกลับที่ประสบความสำเร็จเปรียบเทียบตราประทับกับเคาน์เตอร์เพื่อตรวจสอบว่ามันเป็นคำขอล่าสุด

คร่าวๆของรหัส:

var xhrCount = 0;
function sendXHR() {
    // sequence number for the current invocation of function
    var seqNumber = ++xhrCount;
    $.post("/echo/json/", { delay: Math.floor(Math.random() * 5) }, function() {
        // this works because of the way closures work
        if (seqNumber === xhrCount) {
            console.log("Process the response");
        } else {
            console.log("Ignore the response");
        }
    });
}
sendXHR();
sendXHR();
sendXHR();
// AJAX requests complete in any order but only the last 
// one will trigger "Process the response" message

ตัวอย่างบน jsFiddle


เนื่องจากข้อ จำกัด ในการยกเลิกคำขอ XHR (ดูความคิดเห็นอื่นในหน้านี้) นี่อาจเป็นตัวเลือกที่ดีที่สุดและง่ายที่สุด
ควินน์

41

เราต้องแก้ไขปัญหานี้และทดสอบวิธีที่แตกต่างกันสามวิธี

  1. ยกเลิกคำขอตามที่แนะนำโดย @meouw
  2. ดำเนินการคำขอทั้งหมด แต่ประมวลผลผลลัพธ์ของการส่งครั้งล่าสุดเท่านั้น
  3. ป้องกันคำขอใหม่ตราบเท่าที่ยังมีคำขออื่นค้างอยู่

var Ajax1 = {
  call: function() {
    if (typeof this.xhr !== 'undefined')
      this.xhr.abort();
    this.xhr = $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        //process response
      }
    });
  }
};
var Ajax2 = {
  counter: 0,
  call: function() {
    var self = this,
      seq = ++this.counter;
    $.ajax({
      url: 'your/long/running/request/path',
      type: 'GET',
      success: function(data) {
        if (seq === self.counter) {
          //process response
        }
      }
    });
  }
};
var Ajax3 = {
  active: false,
  call: function() {
    if (this.active === false) {
      this.active = true;
      var self = this;
      $.ajax({
        url: 'your/long/running/request/path',
        type: 'GET',
        success: function(data) {
          //process response
        },
        complete: function() {
          self.active = false;
        }
      });
    }
  }
};
$(function() {
  $('#button').click(function(e) {
    Ajax3.call();
  });
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="button" type="button" value="click" />

ในกรณีของเราเราตัดสินใจที่จะใช้วิธีการ # 3 เพราะมันทำให้โหลดน้อยลงสำหรับเซิร์ฟเวอร์ แต่ฉันไม่แน่ใจ 100% ว่า jQuery รับประกันการโทรของ. complete () - วิธีการนี้สามารถสร้างสถานการณ์การหยุดชะงักได้ ในการทดสอบของเราเราไม่สามารถจำลองสถานการณ์ดังกล่าวได้


36

เป็นการดีที่สุดที่จะทำสิ่งนี้

var $request;
if ($request != null){ 
    $request.abort();
    $request = null;
}

$request = $.ajax({
    type : "POST", //TODO: Must be changed to POST
    url : "yourfile.php",
    data : "data"
    }).done(function(msg) {
        alert(msg);
    });

แต่จะดีกว่ามากถ้าคุณตรวจสอบคำสั่ง if เพื่อตรวจสอบว่าคำขอ ajax เป็นโมฆะหรือไม่


2
ฉันตรวจสอบด้วยว่าคำขอกำลังทำงานอยู่หรือไม่ แต่ฉันใช้บูลีนเพราะเบากว่า
กรุณาคลิกที่นี่

15

เพียงโทร xhr ยกเลิก ()ไม่ว่าจะเป็นวัตถุ ajax jquery หรือวัตถุ XMLHTTPRequest ดั้งเดิม

ตัวอย่าง:

//jQuery ajax
$(document).ready(function(){
    var xhr = $.get('/server');
    setTimeout(function(){xhr.abort();}, 2000);
});

//native XMLHTTPRequest
var xhr = new XMLHttpRequest();
xhr.open('GET','/server',true);
xhr.send();
setTimeout(function(){xhr.abort();}, 2000);

13

ฉันกำลังทำโซลูชันการค้นหาสดและจำเป็นต้องยกเลิกคำขอที่รอดำเนินการซึ่งอาจใช้เวลานานกว่าคำขอล่าสุด / คำขอล่าสุด

ในกรณีของฉันฉันใช้สิ่งนี้:

//On document ready
var ajax_inprocess = false;

$(document).ajaxStart(function() {
ajax_inprocess = true;
});

$(document).ajaxStop(function() {
ajax_inprocess = false;
});

//Snippet from live search function
if (ajax_inprocess == true)
{
    request.abort();
}
//Call for new request 

12

ตามที่หลายคนในเธรดได้จดบันทึกเพียงเพราะคำขอถูกยกเลิกบนฝั่งไคลเอ็นต์เซิร์ฟเวอร์จะยังคงประมวลผลคำขอ สิ่งนี้จะสร้างการโหลดที่ไม่จำเป็นบนเซิร์ฟเวอร์เพราะมันเป็นงานที่เราเลิกฟังต่อหน้า

ปัญหาที่ฉันพยายามแก้ไข (ที่คนอื่นอาจทำเช่นกัน) ก็คือเมื่อผู้ใช้ป้อนข้อมูลในช่องป้อนข้อมูลฉันต้องการยกเลิกคำขอสำหรับความรู้สึกแบบ Google Instant

เพื่อหลีกเลี่ยงการยิงคำขอที่ไม่จำเป็นและเพื่อรักษาความรวดเร็วของ front-end ฉันทำต่อไปนี้:

var xhrQueue = [];
var xhrCount = 0;

$('#search_q').keyup(function(){

    xhrQueue.push(xhrCount);

    setTimeout(function(){

        xhrCount = ++xhrCount;

        if (xhrCount === xhrQueue.length) {
            // Fire Your XHR //
        }

    }, 150);

});

สิ่งนี้จะส่งคำขอหนึ่งครั้งทุกๆ 150 มิลลิวินาที (ตัวแปรที่คุณสามารถปรับแต่งตามความต้องการของคุณเอง) หากคุณมีปัญหาในการทำความเข้าใจสิ่งที่เกิดขึ้นตรงนี้ให้เข้าสู่ระบบxhrCountและxhrQueueคอนโซลก่อนถึง if if


11

เพียงใช้ ajax.abort () ตัวอย่างเช่นคุณสามารถยกเลิกคำขอ ajax ใด ๆ ที่ค้างอยู่ก่อนที่จะส่งแบบนี้อีก

//check for existing ajax request
if(ajax){ 
 ajax.abort();
 }
//then you make another ajax request
$.ajax(
 //your code here
  );

11

คุณสามารถยกเลิกการโทร ajax ต่อเนื่องโดยใช้สิ่งนี้

<input id="searchbox" name="searchbox" type="text" />

<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>

<script type="text/javascript">
     var request = null;
        $('#searchbox').keyup(function () {
            var id = $(this).val();
            request = $.ajax({
                type: "POST", //TODO: Must be changed to POST
                url: "index.php",
                data: {'id':id},
                success: function () {

                },
                beforeSend: function () {
                    if (request !== null) {
                        request.abort();
                    }
                }
            });
        });

</script>

10

ไม่มีวิธีที่เชื่อถือได้ที่จะทำและฉันจะไม่แม้แต่จะลองเมื่อคำขออยู่ในระหว่างการเดินทาง; เพียงวิธีการที่จะตอบสนองพอสมควรคือการละเว้นการตอบสนอง

ในกรณีส่วนใหญ่มันอาจเกิดขึ้นในสถานการณ์เช่น: ผู้ใช้คลิกบ่อยเกินไปบนปุ่มที่เรียก XHR ติดต่อกันมากมายที่นี่คุณมีตัวเลือกมากมายทั้งบล็อกปุ่มจนกว่า XHR จะถูกส่งกลับหรือไม่ได้เรียก XHR ใหม่ในขณะที่อีก ผู้ใช้สามารถเอนหลังหรือทิ้งการตอบสนอง XHR ที่รอดำเนินการ แต่ล่าสุด


7

รหัสต่อไปนี้แสดงให้เห็นถึงการเริ่มต้นเช่นเดียวกับการยกเลิกคำขอ Ajax:

function libAjax(){
  var req;
  function start(){

  req =    $.ajax({
              url: '1.php',
              success: function(data){
                console.log(data)
              }
            });

  }

  function stop(){
    req.abort();
  }

  return {start:start,stop:stop}
}

var obj = libAjax();

 $(".go").click(function(){


  obj.start();


 })



 $(".stop").click(function(){

  obj.stop();


 })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" class="go" value="GO!" >
   <input type="button" class="stop" value="STOP!" >

5
โปรดให้คำอธิบายว่าวิธีนี้แก้ปัญหาได้อย่างไร วิธีนี้จะช่วยให้ OP และผู้ค้นหาในอนาคตอื่น ๆ
SnareChops

5

ฉันมีปัญหาในการทำโพลและเมื่อเพจถูกปิดการสำรวจยังคงดำเนินต่อไปดังนั้นในกรณีของฉันผู้ใช้จะพลาดการอัปเดตเนื่องจากค่า mysql ถูกตั้งค่าสำหรับ 50 วินาทีถัดไปหลังจากปิดหน้าแม้ว่าฉันจะฆ่าอาแจ็กซ์ขอ คิดไปรอบ ๆ โดยใช้ $ _SESSION เพื่อตั้งค่า var จะไม่อัปเดตในการสำรวจความคิดเห็นของตนเองจนกว่าจะสิ้นสุดและเริ่มใหม่ดังนั้นสิ่งที่ฉันได้ตั้งค่าในฐานข้อมูลของฉันเป็น 0 = offpage ในขณะที่ฉัน การสำรวจฉันค้นหาแถวนั้นและส่งกลับค่าเท็จ เมื่อเป็น 0 เมื่อทำการสอบถามแบบสำรวจคุณจะได้รับค่าปัจจุบันอย่างชัดเจน ...

ฉันหวังว่านี่จะช่วยได้


5

หาก xhr.abort(); ทำให้หน้าโหลดซ้ำ

จากนั้นคุณสามารถตั้งค่าonreadystatechangeก่อนที่จะยกเลิกเพื่อป้องกัน:

// ↓ prevent page reload by abort()
xhr.onreadystatechange = null;
// ↓ may cause page reload
xhr.abort();

4

ฉันได้แชร์การสาธิตที่สาธิตวิธีการยกเลิกคำขอ AJAX - หากข้อมูลไม่ถูกส่งคืนจากเซิร์ฟเวอร์ภายในเวลารอที่กำหนดไว้ล่วงหน้า

HTML:

<div id="info"></div>

รหัส JS:

var isDataReceived= false, waitTime= 1000; 
$(function() {
    // Ajax request sent.
     var xhr= $.ajax({
      url: 'http://api.joind.in/v2.1/talks/10889',
      data: {
         format: 'json'
      },     
      dataType: 'jsonp',
      success: function(data) {      
        isDataReceived= true;
        $('#info').text(data.talks[0].talk_title);        
      },
      type: 'GET'
   });
   // Cancel ajax request if data is not loaded within 1sec.
   setTimeout(function(){
     if(!isDataReceived)
     xhr.abort();     
   },waitTime);   
});

1
$.ajaxมีtimeoutตัวเลือกดังนั้นคุณไม่จำเป็นต้องเขียนด้วยตัวเอง ..., data: {...}, timeout: waitTime,...เพียงแค่ใช้
Bram Vanroy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.