Câu hỏi Làm cách nào để jQuery có thể thực hiện yêu cầu Ajax đồng bộ, chứ không phải không đồng bộ?


Tôi có một tiện ích JavaScript cung cấp các điểm mở rộng tiêu chuẩn. Một trong số đó là beforecreate chức năng. Nó sẽ trở lại false để ngăn một mục được tạo ra.

Tôi đã thêm một cuộc gọi Ajax vào hàm này bằng cách sử dụng jQuery:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

Nhưng tôi muốn ngăn tiện ích của tôi tạo mục, vì vậy tôi nên quay lại false trong hàm mẹ, không phải trong hàm gọi lại. Có cách nào để thực hiện một yêu cầu AJAX đồng bộ bằng cách sử dụng jQuery hoặc bất kỳ API trong trình duyệt nào khác không?


1052
2017-09-25 13:26


gốc


Cách thích hợp để giải quyết điều đó sẽ là viết lại các lời hứa sử dụng điểm mở rộng của tiện ích của bạn. Bằng cách này sẽ dễ dàng cho phép bạn thiết lập một hành động không đồng bộ (như một yêu cầu ajax) như beforecreate. - Kos
Tôi đề xuất chức năng Sajak. Chúng ta có chữ T không? Có vanna, cho tôi 3 T. - Cody O'Dell
@Kos là điểm trên. Không yêu cầu đồng bộ XHR tại đây - Michael Westcott
Nếu mọi người hỏi tôi 1 lời khuyên khi bắt đầu javascript, tôi nói: nắm lấy ký tự không đồng bộ của javascript, đừng cố gắng chống lại điều đó. - Emmanuel Delay
Bạn có thể thử sử dụng embeddedjs.com - firstpostcommenter


Các câu trả lời:


Từ Tài liệu jQuery: bạn chỉ định không đồng bộ tùy chọn để trở thành sai để nhận yêu cầu Ajax đồng bộ. Sau đó, cuộc gọi lại của bạn có thể đặt một số dữ liệu trước khi tiền của bạn được thực hiện.

Dưới đây là mã của bạn sẽ trông như thế nào nếu được thay đổi như được đề xuất:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

1034
2017-09-25 13:30



Chính xác, không thể sử dụng get (), post (), load () cho các cuộc gọi đồng bộ. Chỉ ajax () có tham số "async", có thể được đặt thành "false". - SLA80
@ SLA80 Không. Kể từ jQuery 1.1: stackoverflow.com/questions/6849686/… - StuperUser
@qualidafial bình luận của tôi là nhằm vào bình luận không chính xác của SLA80; có thể sử dụng get (), post (), load () cho các cuộc gọi đồng bộ. - StuperUser
false không đồng bộ không còn được hỗ trợ cho jQuery> = 1.8. Tham khảo api.jquery.com/jQuery.ajax - ken
@ken async: false vẫn được hỗ trợ trong jQuery> = 1.8. Khả năng sử dụng async: false với jqXHR ($.Deferred) là những gì không được chấp nhận. Nói cách khác, người ta phải sử dụng các tùy chọn gọi lại thành công / lỗi / hoàn thành mới hơn, thay vì các phương pháp kế thừa, ví dụ: jqXHR.done(). - Ben Johnson


Bạn có thể đặt thiết lập Ajax của jQuery ở chế độ đồng bộ bằng cách gọi

jQuery.ajaxSetup({async:false});

Và sau đó thực hiện các cuộc gọi Ajax của bạn bằng cách sử dụng jQuery.get( ... );

Sau đó, chỉ bật lại một lần

jQuery.ajaxSetup({async:true});

Tôi đoán nó hoạt động tương tự như đề xuất của @Adam, nhưng nó có thể hữu ích cho ai đó mà không muốn cấu hình lại jQuery.get() hoặc là jQuery.post() đến phức tạp hơn jQuery.ajax() cú pháp.


237
2018-04-12 21:45



Đây là một ý tưởng thực sự tồi tệ, tại sao bạn sẽ đặt nó ở cấp độ toàn cầu? Và sau đó bị buộc phải bỏ nó sau? - Juan Mendes
Ít nhất, đây là ý tưởng tồi nhất. thay vì nói: "KHÔNG CÓ THÌ BAO GIỜ $.ajax()".;) - Rzassar
Không nên được đặt trên toàn cầu .. - 0kay


Giải pháp tuyệt vời! Tôi nhận thấy khi tôi cố gắng thực hiện nó nếu tôi trả về một giá trị trong mệnh đề thành công, nó trở lại như không xác định. Tôi đã phải lưu nó trong một biến và trả về biến đó. Đây là phương pháp tôi đưa ra:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}

125
2018-04-07 13:30



Đó là bởi vì bạn đã trả lại một giá trị trong số các cuộc gọi lại, không phải trong số getWhatever. Vì vậy bạn đã quay trở lại không có gì I E. undefined từ của bạn getWhatever. - Lightness Races in Orbit
điều này hoàn toàn sai. Bạn không thể chắc chắn rằng một cuộc gọi không đồng bộ đã kết thúc khi trả về 'strReturn'. - Thomas Fritz
Đây là cuộc gọi Đồng bộ (không đồng bộ: sai). - James in Indy


Tất cả các câu trả lời đều bỏ lỡ điểm thực hiện cuộc gọi Ajax với async: false sẽ khiến trình duyệt bị treo cho đến khi yêu cầu Ajax hoàn tất. Sử dụng thư viện điều khiển luồng sẽ giải quyết vấn đề này mà không cần treo trình duyệt. Đây là một ví dụ với Frame.js:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

82
2018-04-28 17:41



Các cuộc gọi đồng bộ rất thuận tiện nếu bạn muốn kết hợp một khai thác thử nghiệm nhanh chóng cho một kết thúc REST và muốn đơn giản hơn địa ngục gọi lại. - Steve Taylor


function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

49
2018-04-25 15:34



Lưu ý rằng mặc dù, bạn có thể nhận được điều này: 'XMLHttpRequest đồng bộ trên chủ đề chính không được chấp nhận vì tác động bất lợi của nó đến trải nghiệm của người dùng cuối.' - Hari
@ Hari Cách thực hiện cuộc gọi ajax đồng bộ bằng jQuery mà không sử dụng chủ đề chính là gì? - Jose Nobile
Tôi không thấy rằng câu trả lời này có bất cứ điều gì để cung cấp, nó chỉ là câu trả lời chấp nhận được bọc vào một chức năng và trả lời bốn năm sau đó. Đó là một điều xấu để khuyên mọi người với C + P, bởi vì chức năng không cho biết nó làm gì. "Vì thế getURL so với get ? tại sao một trình duyệt của tôi bị treo? " - moopet


Hãy nhớ rằng nếu bạn đang thực hiện cuộc gọi Ajax tên miền chéo (bằng cách sử dụng JSONP) - bạn không thể làm điều đó một cách đồng bộ, async cờ sẽ bị jQuery bỏ qua.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

Đối với các cuộc gọi JSONP, bạn có thể sử dụng:

  1. Ajax gọi đến miền của riêng bạn - và thực hiện cuộc gọi phía máy chủ tên miền chéo
  2. Thay đổi mã của bạn để hoạt động không đồng bộ
  3. Sử dụng thư viện "sequencer function" như Frame.js (điều này câu trả lời)
  4. Chặn giao diện người dùng thay vì chặn thực thi (điều này câu trả lời) (cách yêu thích của tôi)

22
2018-05-10 06:28





Lưu ý: Bạn không nên sử dụng async do điều này:

Bắt đầu với Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), các yêu cầu đồng bộ trên chủ đề chính đã không được chấp nhận do tác động tiêu cực đến trải nghiệm người dùng.

Chrome thậm chí còn cảnh báo về điều này trong bảng điều khiển:

XMLHttpRequest đồng bộ trên chuỗi chính không được chấp nhận vì các hiệu ứng bất lợi của nó đối với trải nghiệm của người dùng cuối. Để được trợ giúp thêm, hãy kiểm tra https://xhr.spec.whatwg.org/.

Điều này có thể phá vỡ trang của bạn nếu bạn đang làm một cái gì đó như thế này vì nó có thể ngừng làm việc bất cứ ngày nào.

Nếu bạn muốn làm điều đó một cách mà vẫn cảm thấy như nếu nó đồng bộ nhưng vẫn không chặn thì bạn nên sử dụng async / await và có lẽ cũng một số ajax dựa trên những lời hứa như mới Tìm nạp API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

17
2017-12-13 12:55



Lưu ý rằng bạn nên quấn await fetch(url) gọi trong một try... catch chặn bất kỳ lỗi không đồng bộ nào. - inostia
hàm foo đã được chuyển đổi thành lời hứa bằng cách chỉ sử dụng từ async ngay từ đầu, vì vậy bạn có thể làm foo().catch(...) để bắt nó - Endless