2009-07-20 46 views
21

Tôi sử dụng jQuery. Và tôi không muốn các cuộc gọi AJAX song song trên ứng dụng của tôi, mỗi cuộc gọi phải đợi trước đó trước khi bắt đầu. Làm thế nào để thực hiện nó? Có người trợ giúp nào không?Làm thế nào để thực hiện tất cả các cuộc gọi AJAX tuần tự?

CẬP NHẬT Nếu có bất kỳ phiên bản đồng bộ nào của XMLHttpRequest hoặc jQuery.post tôi muốn biết. Nhưng tuần tự! = Đồng bộ, và tôi muốn một giải pháp không đồng bộ và tuần tự.

+4

Bạn biết những gì "A" trong AJAX là viết tắt của, phải :-) –

+2

này chắc chắn tôi không phải là một câu trả lời, nhưng đó là một dấu hiệu thú vị của một framework được thiết kế tốt khi * this * là câu hỏi khó hiểu thay vì cách làm cho nó đồng thời. :) –

+8

@Ed Swangren, vâng nhưng AJAX không phải là không đồng bộ, JavaScript hoặc XML. :-) – Nosredna

Trả lời

14

Có một cách tốt hơn để làm điều này là sử dụng các cuộc gọi ajax đồng bộ. Jquery ajax trả về giá trị hoãn lại để bạn có thể sử dụng chuỗi đường ống để đảm bảo rằng mỗi cuộc gọi ajax kết thúc trước lần chạy tiếp theo. Đây là một ví dụ làm việc với một ví dụ sâu hơn, bạn có thể play with on jsfiddle.

// How to force async functions to execute sequentially 
// by using deferred pipe chaining. 

// The master deferred. 
var dfd = $.Deferred(), // Master deferred 
    dfdNext = dfd; // Next deferred in the chain 
    x = 0, // Loop index 
    values = [], 

    // Simulates $.ajax, but with predictable behaviour. 
    // You only need to understand that higher 'value' param 
    // will finish earlier. 
    simulateAjax = function (value) { 
     var dfdAjax = $.Deferred(); 

     setTimeout(
      function() { 
       dfdAjax.resolve(value); 
      }, 
      1000 - (value * 100) 
     ); 

     return dfdAjax.promise(); 
    }, 

    // This would be a user function that makes an ajax request. 
    // In normal code you'd be using $.ajax instead of simulateAjax. 
    requestAjax = function (value) { 
     return simulateAjax(value); 
    }; 

// Start the pipe chain. You should be able to do 
// this anywhere in the program, even 
// at the end,and it should still give the same results. 
dfd.resolve(); 

// Deferred pipe chaining. 
// What you want to note here is that an new 
// ajax call will not start until the previous 
// ajax call is completely finished. 
for (x = 1; x <= 4; x++) { 

    values.push(x); 

    dfdNext = dfdNext.pipe(function() { 
     var value = values.shift(); 
     return requestAjax(value). 
      done(function(response) { 
       // Process the response here. 

      }); 

    }); 

} 

Một số người đã nhận xét rằng họ không biết đầu vào của mã. Để hiểu nó, trước tiên bạn cần phải hiểu lời hứa javascript. Tôi khá chắc chắn hứa hẹn sẽ sớm trở thành một tính năng ngôn ngữ javascript bản địa, do đó sẽ cung cấp cho bạn một động lực tốt để tìm hiểu.

+0

Hey, đây là một chút muộn nhưng anyways: Great câu trả lời đã giúp tôi ra ngoài và hoạt động như một say mê. Nhưng tôi thực sự không hiểu nó hoạt động ra sao. Tôi đã cố gắng để hiểu và đọc các tài liệu, nhưng đây là một bí ẩn đối với tôi. –

+0

@DanLee Có vẻ như bạn không phải là người duy nhất. –

+0

Khó hiểu các lời hứa javascript và cách jquery thực hiện khái niệm mà không cần học nó ;-) Rất nhiều tài liệu trên mạng. –

6

Bạn có hai lựa chọn mà tôi có thể nghĩ đến. Một là kết nối chúng thông qua callbacks. Cách khác là thực hiện cuộc gọi đồng bộ thay vì không đồng bộ.

Có lý do nào bạn muốn chúng tuần tự không? Điều đó sẽ làm chậm mọi thứ.

Để thực hiện cuộc gọi đồng bộ, bạn sẽ đặt tùy chọn không đồng bộ trong cuộc gọi Ajax thành sai. Xem tài liệu tại http://docs.jquery.com/Ajax/jQuery.ajax#options (tab tùy chọn nhấp để xem chúng).

+0

Làm sao để chúng đồng bộ? –

+0

Hoặc tùy chọn thứ ba: một lớp sẽ quản lý hàng đợi yêu cầu và xử lý tuần tự theo yêu cầu. –

+0

Tôi đã chỉnh sửa câu trả lời của mình để trỏ đến các tùy chọn Ajax. Đặt tùy chọn async thành false. – Nosredna

1

Nhìn vào điều này: http://docs.jquery.com/Ajax/jQuery.ajax (nhấp vào tab "tùy chọn"). Nhưng hãy nhớ rằng một cuộc gọi đồng bộ sẽ đóng băng trang cho đến khi nhận được phản hồi, vì vậy nó không thể được sử dụng trong một trang web sản xuất, bởi vì người dùng sẽ phát điên nếu vì lý do nào đó họ phải đợi 30 giây khi trình duyệt của họ bị đóng băng .

EDIT: ok, với bản cập nhật của bạn đó là rõ ràng hơn những gì bạn muốn đạt được;)

Vì vậy, mã của bạn có thể trông như thế này:

$.getJSON("http://example.com/jsoncall", function(data) { 
     process(data); 
     $.getJSON("http://example.com/jsoncall2", function (data) { 
      processAgain(data); 
      $.getJSON("http://example.com/anotherjsoncall", function(data) { 
       processAgainAndAgain(data); 
      }); 
     }); 
    }); 

Bằng cách này, cuộc gọi thứ hai sẽ chỉ được ban hành khi phản hồi cho cuộc gọi đầu tiên đã được nhận và xử lý và cuộc gọi thứ ba sẽ chỉ được phát hành khi phản hồi cho cuộc gọi thứ hai đã được nhận và xử lý. Mã này dành cho getJSON nhưng nó có thể thích nghi với $ .ajax.

+0

Tôi nhận thức được giải pháp của bạn, nhưng yêu cầu nhiều không được tạo ra bởi cùng một thậm chí, vì vậy tôi không thể chuỗi chúng lại với nhau như bạn đã cho thấy.Giải pháp của tôi sẽ giống như một khóa (globalAjaxObject) trong C# –

1

Cách tốt nhất bạn có thể làm điều này là bằng cách chuỗi các cuộc gọi lại như Nosredna nói. Tôi sẽ không khuyên bạn sử dụng XMLHttpRequest đồng bộ khi họ khóa toàn bộ ứng dụng của bạn.

Không có nhiều trợ giúp cho điều này theo như tôi biết, nhưng bạn có thể làm điều gì đó giống như một cuộc gọi lại FIFO.

2

Bạn có thể cung cấp cho câu chuyện javascript một thử http://www.neilmix.com/narrativejs/doc/

Tôi chưa bao giờ sử dụng nó bản thân mình mặc dù. Nếu tôi muốn làm điều này, tôi sẽ thiết lập một số loại trừu tượng cho chuỗi hành động không đồng bộ. Như những người khác đã nói, phiên bản đồng bộ của đối tượng ajax chặn các sự kiện đang được xử lý trong khi chờ đợi phản hồi. Điều này làm cho trình duyệt trông giống như trình duyệt bị đóng băng cho đến khi nó nhận được phản hồi.

+1

Điều đó có vẻ thú vị. – Nosredna

+0

Cảm ơn bạn đã bổ sung, nhưng tôi không chắc liệu nó có giải quyết được vấn đề của tôi hay không. Nó làm cho các cuộc gọi async tuần tự nếu chỉ có một luồng tạo ra, nhưng trong trường hợp của tôi, nhiều sự kiện sinh ra các yêu cầu. –

+0

Như tôi đã nói, tôi đã không sử dụng NJS, nhưng mô tả của nó nói rằng nó thêm một toán tử lợi nhuận đơn giản dừng việc thực hiện một hàm cho đến khi một sự kiện đã được kích hoạt. Dường như với tôi như thế sẽ ngăn cản sự tương tranh. Nếu nó đã làm, nó sẽ không phải là một thư viện rất hữu ích cho bất cứ ai. – Breton

3

Đặt tùy chọn async false, ví dụ:

$.ajax({ async: false /*, your_other_ajax_options_here */ }); 

tham khảo: Ajax/jQuery.ajax

+0

Tùy chọn async sẽ sớm bị xóa khỏi jQuery. –

+0

Đây là câu trả lời hay nhất cho yêu cầu ban đầu của OP. Đề xuất này đảm bảo IOE (theo thứ tự thực hiện) với độ phức tạp thấp nhất. Chưa bao giờ có kế hoạch loại bỏ cờ async khỏi jquery, trái với những gì @LS ngụ ý. – kamelkev

+1

Hãy nhớ rằng: "Kể từ jQuery 1.8, việc sử dụng async: false với jqXHR ($ .Deferred) không được dùng nữa, bạn 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 thay vì các phương thức tương ứng của đối tượng jqXHR chẳng hạn như jqXHR.done(). " http://docs.jquery.com/Ajax/jQuery.ajax#options –

0

cuộc gọi đồng bộ không nhất thiết phải chậm hơn, nếu bạn có một ứng dụng mà AJAX gọi mở, bài viết để, sau đó đóng socket, nhiều cuộc gọi đến socket không có ý nghĩa vì một số socket chỉ có thể xử lý một kết nối, trong trường hợp này, xếp hàng dữ liệu sao cho chỉ được gửi khi cuộc gọi AJAX trước đó hoàn thành có nghĩa là thông lượng dữ liệu cao hơn nhiều.

-1

Cách sử dụng các sự kiện Node.js?

var EventEmitter = require('events').EventEmitter; 
var eventEmitter = new EventEmitter(); 
var $ = require('jquery'); 

var doSomething = function (responseData) { 
    var nextRequestData = {}; 
    // do something with responseData 
    return nextRequestData; 
}; 

// ajax requests 
var request1 = $.ajax; 
var request2 = $.ajax; 
var requests = [request1, request2]; 

eventEmitter.on('next', function (i, requestData) { 
    requests[i](requestData).then(
    function (responseData) { 
     console.log(i, 'request completed'); 
     if (i+1 < requests.length) { 
     var nextRequestData = doSomething(responseData); 
     eventEmitter.emit('next', i+1, nextRequestData); 
     } 
     else { 
     console.log('completed all requests'); 
     } 
    }, 
    function() { 
     console.log(i, 'request failed'); 
    } 
); 
}); 

var data = { 
    //data to send with request 1 
}; 
eventEmitter.emit('next', 0, data); 
0

tuần tự! = Đồng bộ, và tôi muốn một không đồng bộ và giải pháp tuần tự

thực hiện đồng bộ thường có nghĩa là "sử dụng cùng một đồng hồ", trong khi thực hiện tuần tự có nghĩa là "sau theo thứ tự hoặc chuỗi ".

Đối với trường hợp sử dụng cụ thể của bạn, tôi nghĩ rằng cả hai điều kiện phải được đáp ứng, vì việc thực thi không đồng bộ ngụ ý khả năng kết quả không tuần tự.

0
(async() => { 
    for(f of ['1.json','2.json','3.json']){ 
    var json = await $.getJSON(f); 
    console.log(json) 
}; 
})() 
  1. yêu cầu 3 file json với jQuery ajax gọi
  2. quá trình theo thứ tự (không song song) với chờ đợi
  3. công trình trong Chrome/Firefox/Edge (tính 2018/01/30)

hơn tại MDN

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