Có bất kỳ lý do gì để sử dụng một XMLHttpRequest đồng bộ không?


88

Có vẻ như hầu hết mọi người đều thực hiện các yêu cầu không đồng bộ với XMLHttpRequest nhưng rõ ràng thực tế là có khả năng thực hiện các yêu cầu đồng bộ cho thấy có thể có lý do hợp lệ để làm như vậy. Vậy lý do hợp lệ đó có thể là gì?


1
Đó là một câu hỏi khá hay! Tôi không nghĩ câu trả lời sẽ rất thú vị, nhưng câu hỏi rất hay. Bạn đã thử gọi đồng bộ để xem điều gì sẽ xảy ra chưa?
Tad Donaghe

3
Các cuộc gọi đồng bộ chặn trình duyệt, dẫn đến trải nghiệm người dùng tồi tệ. Vì vậy, câu hỏi của tôi. Tôi không thể nghĩ ra lý do chính đáng nào để sử dụng nó.
Darrell Brogdon

2
Câu trả lời hơi nghiêm túc: có thể chỉ đơn giản là điền vào chương trước yêu cầu không đồng bộ trong bất kỳ cuốn sách JavaScript nào bạn đang đọc.
Ben James

Cá nhân tôi muốn sử dụng một số ajax đồng bộ để gói nhiều cuộc gọi đến các hàm bên máy chủ mà không cần phải viết yêu cầu cho mỗi cuộc gọi.
Paul Ishak

chạy mã cục bộ, đặc biệt là cho các công cụ và khuôn khổ nhà phát triển nội bộ.
user2800679

Câu trả lời:


25

Tôi nghĩ chúng có thể trở nên phổ biến hơn khi các tiêu chuẩn HTML 5 tiến bộ. Nếu một ứng dụng web được cấp quyền truy cập cho nhân viên web, tôi có thể thấy trước các nhà phát triển sử dụng nhân viên web chuyên dụng để đưa ra các yêu cầu đồng bộ, như Jonathan đã nói, để đảm bảo yêu cầu này xảy ra trước yêu cầu khác. Với tình hình hiện tại của một luồng, đó là một thiết kế kém lý tưởng vì nó sẽ chặn cho đến khi yêu cầu hoàn thành.


16
Tôi cho rằng ông có nghĩa là 'Web Workers'
evilpie

Tôi nghĩ rằng điểm chắt lọc. Trong Chuỗi giao diện người dùng, Tạo một chuỗi hoặc một nhiệm vụ không đồng bộ. Nếu đã có trong chuỗi, hãy sử dụng đồng bộ hóa trong hầu hết các trường hợp. Chủ đề "thân thiện với khối" hơn rất nhiều
HaMMeReD

Đây là một câu trả lời cũ, nhưng nhận xét này áp dụng cho cả hồi đó, thậm chí trước HTML5, các trình duyệt cung cấp 2 luồng để đưa ra yêu cầu. Tôi đã viết một tập lệnh nhóm kết nối để sử dụng cả hai, vì ngay cả với yêu cầu không đồng bộ, với một kết nối, bạn có thể buộc trình duyệt. Việc sử dụng cả hai cho phép nhiều dữ liệu được đẩy / kéo qua đường truyền; nhưng iirc, tôi nghĩ rằng các yêu cầu đồng bộ hóa vẫn ràng buộc trình duyệt.
vol7ron

Firefox (và có thể là tất cả các trình duyệt không phải IE) không hỗ trợ XHR timeOut không đồng bộ. HTML5 WebWorkers hỗ trợ hết thời gian chờ. Vì vậy, bạn có thể muốn bao bọc yêu cầu XHR đồng bộ với WebWorker với thời gian chờ để triển khai XHR giống như không đồng bộ với hành vi thời gian chờ.
Dmitry Kaigorodov

1
-1. Đây không phải là câu trả lời nhiều và toàn bộ cuộc thảo luận về các chủ đề chỉ làm rối ren vấn đề. Câu trả lời dưới đây của Sami thực sự tốt hơn nhiều.
Stijn de Witt,

30

XHR đồng bộ rất hữu ích để tiết kiệm dữ liệu người dùng. Nếu bạn xử lý beforeunloadsự kiện, bạn có thể tải dữ liệu lên máy chủ khi người dùng đóng trang.

Nếu điều này được thực hiện bằng cách sử dụng tùy chọn không đồng bộ, thì trang có thể đóng trước khi yêu cầu hoàn tất. Thực hiện điều này một cách đồng bộ đảm bảo yêu cầu hoàn thành hoặc không thành công theo cách mong đợi.


4
Đã chỉnh sửa: Tôi nhận ra rằng bạn chỉ đổ txt từ một người dùng HN lười biếng, nhưng một chút thời gian để viết nó độc đáo được đánh giá cao ở đây trên SO.
Frank Krueger

Nhưng thực sự đây là lý do hợp lệ duy nhất mà tôi thấy cho đến nay.
Stijn de Witt,

@Frank Krueger HN là gì?
Douglas Tổ chức

1
@DouglasHeld Một trang web có tên Hacker News tại news.ycombinator.com
Sami Samhuri

13

Cập nhật:

Điều dưới đây gợi ý - nhưng không thành công trong việc phân phối - rằng với sự ra đời của xử lý yêu cầu không đồng bộ tốt hơn, thực sự không có lý do gì để sử dụng các yêu cầu đồng bộ, trừ khi có ý định cố tình chặn người dùng làm bất cứ điều gì cho đến khi một yêu cầu hoàn tất - nghe có vẻ độc hại: )

Mặc dù, điều này nghe có vẻ không tốt, nhưng có thể có những lúc điều quan trọng là một yêu cầu (hoặc một loạt yêu cầu) xảy ra trước khi người dùng rời khỏi trang hoặc trước khi một hành động được thực hiện - việc chặn thực thi mã khác (ví dụ: ngăn nút quay lại) có thể có thể giảm lỗi / bảo trì cho một hệ thống được thiết kế kém ; điều đó nói rằng, tôi chưa bao giờ nhìn thấy nó trong tự nhiên và nhấn mạnh rằng nó nên được tránh.

Các thư viện, giống như lời hứa , giả định tính đồng bộ bằng cách xâu chuỗi các quy trình thông qua các lệnh gọi lại. Điều này phù hợp với phần lớn nhu cầu phát triển, nơi mong muốn có các sự kiện có thứ tự, không chặn cho phép trình duyệt duy trì khả năng đáp ứng cho người dùng (UX tốt).

Như đã nêu trong tài liệu Mozilla, có những trường hợp bạn phải sử dụng các yêu cầu đồng bộ; tuy nhiên, cũng được liệt kê là một giải pháp thay thế sử dụng beacon (không có sẵn trong IE / Safari) cho những trường hợp như vậy. Trong khi điều này là thử nghiệm, nếu nó đạt được tiêu chuẩn chấp nhận, nó có thể đóng một chiếc đinh vào quan tài yêu cầu đồng bộ.


Bạn muốn thực hiện các lệnh gọi đồng bộ trong bất kỳ loại xử lý giống như giao dịch nào hoặc bất kỳ nơi nào cần thiết bất kỳ thứ tự hoạt động nào.

Ví dụ: giả sử bạn muốn tùy chỉnh một sự kiện để đăng xuất bạn sau khi chơi một bài hát. Nếu thao tác đăng xuất xảy ra trước, thì bài hát sẽ không bao giờ được phát. Điều này yêu cầu đồng bộ hóa các yêu cầu.

Một lý do khác là khi làm việc với WebService, đặc biệt là khi thực hiện phép toán trên máy chủ.

Ví dụ: Máy chủ có một biến có giá trị là 1.

 Step (1) Perform Update: add 1 to variable
 Step (2) Perform Update: set variable to the power of 3
 End Value: variable equals 8

Nếu Bước (2) xảy ra trước, thì giá trị cuối là 2, không phải 8; do đó thứ tự hoạt động các vấn đề và đồng bộ hóa là cần thiết.


Có rất ít lần một lệnh gọi đồng bộ có thể được chứng minh trong một ví dụ phổ biến trong thế giới thực. Có lẽ khi nhấp vào đăng nhập và sau đó nhấp vào một phần của trang web yêu cầu người dùng phải đăng nhập.

Như những người khác đã nói, nó sẽ trói buộc trình duyệt của bạn, vì vậy hãy tránh xa nó khi bạn có thể.

Tuy nhiên, thay vì các cuộc gọi đồng bộ, người dùng thường muốn dừng một sự kiện hiện đang tải và sau đó thực hiện một số thao tác khác. Theo một cách nào đó, đây là đồng bộ hóa, vì sự kiện đầu tiên bị thoát trước khi sự kiện thứ hai bắt đầu. Để thực hiện việc này, hãy sử dụng phương thức abort () trên đối tượng kết nối xml.


1
Tôi nghĩ rằng đây sẽ là câu trả lời đúng

3
@Zack: đó là một ví dụ điển hình, tuy nhiên bạn có thể làm tương tự với các lệnh gọi không đồng bộ tùy thuộc vào sự kiện đang gọi nó.
vol7ron

3
+1 Có một trường hợp hợp lệ là các điều kiện chạy đua hợp lý có thể là kết quả của các yêu cầu máy chủ không đồng bộ ... Tuy nhiên, giải pháp không nhất thiết phải đồng bộ. Trừ khi các yêu cầu của bạn đang được xử lý từ Web Worker, tốt hơn là bạn nên viết một lớp truyền tải sẽ đánh số các yêu cầu và sau đó đảm bảo các hoạt động được xử lý theo thứ tự id yêu cầu.
Roy Tinker

3
-1 Xử lý giao dịch là một ví dụ hoàn hảo trong đó bạn phải sử dụng bảo đảm rằng mọi thứ không thành công hoặc thành công - chỉ vì lệnh đồng bộ, không có nghĩa là yêu cầu đầu tiên đã thành công ... bạn phải dựa vào phản hồi cho bạn biết như vậy. Trong ví dụ này, bạn sẽ thực hiện yêu cầu thứ hai chỉ từ bên trong trình xử lý kết quả của yêu cầu đầu tiên - trong trường hợp này, cả hai đều có thể là không đồng bộ.
Mathew

2
@Mathew: điều đó chỉ đúng nếu quy trình giống như giao dịch của bạn phụ thuộc vào kết quả của hành động trước đó. Nếu bạn có một nút tạo một đối tượng mới (được truy xuất từ ​​máy chủ) trong trang của bạn; nếu nó không đồng bộ, người dùng có thể nhấp nhiều lần và trả về nhiều đối tượng. Một lệnh gọi đồng bộ sẽ ngăn chặn điều đó và chỉ cho phép một đối tượng mới khác được tạo sau khi đối tượng đầu tiên kết thúc, bất kể nó có lỗi hay không. Hãy chú ý đến từ ngữ, tôi đã làm cho nó giống như giao dịch chứ không phải giao dịch có chủ đích.
vol7ron 17/10/12

8

Tôi muốn nói rằng nếu bạn xem xét việc chặn trình duyệt của người dùng trong khi yêu cầu hoàn thành có thể chấp nhận được, thì hãy sử dụng một yêu cầu đồng bộ.

Nếu mục đích của bạn là tuần tự hóa các yêu cầu, thì điều này có thể được thực hiện bằng cách sử dụng các yêu cầu không đồng bộ, bằng cách gọi lại onComplete của yêu cầu trước đó của bạn kích hoạt dòng tiếp theo.


1
Hmm, tôi muốn thêm một cửa sổ trượt vào đó, nếu không bạn sẽ mất cơ bản thời gian khứ hồi cho mỗi yêu cầu
Stephan Eggermont

8

Có rất nhiều trường hợp trong thế giới thực mà việc chặn giao diện người dùng chính xác là hành vi mong muốn.

Lấy một ứng dụng có nhiều trường và một số trường phải được xác thực bằng lệnh gọi xmlhttp tới máy chủ từ xa cung cấp giá trị của trường này và các giá trị khác của trường làm đầu vào.

Trong chế độ đồng bộ, logic rất đơn giản, quá trình chặn mà người dùng trải qua là rất ngắn và không có vấn đề gì.

Trong chế độ không đồng bộ, người dùng có thể thay đổi giá trị của bất kỳ trường nào khác trong khi trường ban đầu đang được xác thực. Những thay đổi này sẽ kích hoạt các lệnh gọi xmlhttp khác với các giá trị từ trường ban đầu chưa được xác thực. Điều gì xảy ra nếu xác thực ban đầu không thành công? Một mớ hỗn độn. Nếu chế độ đồng bộ không được chấp nhận và bị cấm, logic ứng dụng sẽ trở thành cơn ác mộng để xử lý. Về cơ bản ứng dụng phải được viết lại để quản lý khóa (ví dụ: vô hiệu hóa các mục khác trong quá trình xác nhận). Độ phức tạp của mã tăng lên rất nhiều. Không làm như vậy có thể dẫn đến lỗi logic và cuối cùng là hỏng dữ liệu.

Về cơ bản, câu hỏi đặt ra là: trải nghiệm UI không bị chặn hay nguy cơ hỏng dữ liệu quan trọng hơn là gì? Câu trả lời sẽ nằm ở nhà phát triển ứng dụng, không phải W3C.


1
Tôi nghĩ bạn đang nhầm lẫn giữa ý tưởng chặn tương tác của người dùng với việc chặn chuỗi trình duyệt. Có hàng tỷ cách, đơn giản, để ngăn người dùng tiếp tục tương tác với bất kỳ thực thể nhất định nào (trường biểu mẫu, v.v.) trong một lệnh gọi không đồng bộ mà không yêu cầu chặn chuỗi trình duyệt. Khi luồng bị chặn, không thể có bất kỳ xử lý logic nào, và đó chỉ là một tình huống xấu xảy ra; nó tạo ra nhiều vấn đề / vấn đề tiềm ẩn, hầu như không thể giải quyết được, hơn là giải quyết.
Luke Chavers

6

Tôi có thể thấy cách sử dụng cho các yêu cầu XHR đồng bộ được sử dụng khi một tài nguyên ở một vị trí thay đổi phải được tải trước khi các tài nguyên tĩnh khác trong trang phụ thuộc vào tài nguyên đầu tiên hoạt động đầy đủ. Trên thực tế, tôi đang triển khai một yêu cầu XHR như vậy trong một dự án con nhỏ của riêng tôi, trong khi tài nguyên JavaScript nằm ở các vị trí thay đổi trên máy chủ tùy thuộc vào một tập hợp các tham số cụ thể. Các tài nguyên JavaScript tiếp theo dựa trên các tài nguyên biến đổi đó và các tệp đó PHẢI được đảm bảo tải trước khi các tệp phụ thuộc khác được tải, do đó làm cho ứng dụng trở nên toàn vẹn.

Nền tảng ý tưởng đó thực sự mở rộng theo câu trả lời của vol7ron. Các thủ tục dựa trên giao dịch thực sự là thời điểm duy nhất mà các yêu cầu đồng bộ nên được thực hiện. Trong hầu hết các trường hợp khác, các cuộc gọi không đồng bộ là lựa chọn thay thế tốt hơn, trong đó sau cuộc gọi, DOM được cập nhật khi cần thiết. Trong nhiều trường hợp, chẳng hạn như hệ thống dựa trên người dùng, bạn có thể khóa một số tính năng nhất định đối với "người dùng trái phép" cho đến khi họ đăng nhập. Các tính năng đó, sau cuộc gọi không đồng bộ, được mở khóa thông qua quy trình cập nhật DOM.

Cuối cùng tôi phải nói rằng tôi đồng ý với quan điểm của hầu hết các cá nhân về vấn đề này: bất cứ khi nào có thể, nên tránh các yêu cầu XHR đồng bộ vì, với cách thức hoạt động, trình duyệt sẽ khóa các lệnh gọi đồng bộ. Khi triển khai các yêu cầu đồng bộ, chúng nên được thực hiện theo cách mà trình duyệt thường bị khóa, dù sao, hãy nói trong phần HEAD trước khi quá trình tải trang thực sự xảy ra.


Thực tế là một hành động dựa trên kết quả của một hành động khác thì không có lý do gì để thực hiện hành động khác đó một cách đồng bộ. Chỉ khi kết quả của một số hành động phải được xử lý trước khi hàm gọi kết thúc thì bạn mới cần một lệnh gọi đồng bộ.
Stijn de Witt,

5

Tính đến năm 2015, các ứng dụng javascript trên máy tính để bàn đang trở nên phổ biến hơn. Thông thường trong các ứng dụng đó khi tải các tệp cục bộ (và tải chúng bằng XHR là một tùy chọn hoàn toàn hợp lệ), tốc độ tải nhanh đến mức có rất ít điểm làm phức tạp mã với không đồng bộ. Tất nhiên có thể có những trường hợp không đồng bộ là cách để đi (yêu cầu nội dung từ internet, tải các tệp thực sự lớn hoặc một số lượng lớn tệp trong một lô duy nhất), nhưng nếu không thì đồng bộ hóa hoạt động tốt (và dễ sử dụng hơn nhiều) .


Đây thực sự là tình huống tôi gặp phải và đó là năm 2020. Tôi có một ứng dụng dành cho máy tính để bàn hiển thị giao diện người dùng của nó qua HTTP để bạn có thể truy cập nó từ một trình duyệt chạy trên máy cục bộ hoặc thậm chí trên mạng. Trong các tình huống này, mạng nhanh và đáng tin cậy, do đó thực hiện các yêu cầu XHR đồng bộ là một cách tuyệt vời để giữ cho mã đơn giản. Hầu hết mọi người không nhận ra rằng các yêu cầu XHR không đồng bộ giống như sử dụng các luồng và điều đó có thể thực sự phức tạp với nhiều cơ hội phát sinh lỗi.
Eric Mutta

4

jQuery sử dụng AJAX đồng bộ bên trong trong một số trường hợp. Khi chèn HTML có chứa script, trình duyệt sẽ không thực thi chúng. Các tập lệnh cần được thực thi thủ công. Các tập lệnh này có thể đính kèm các trình xử lý nhấp chuột. Giả sử người dùng nhấp vào một phần tử trước khi trình xử lý được đính kèm và trang sẽ không hoạt động như dự định. Do đó, để ngăn chặn các điều kiện đua, AJAX đồng bộ sẽ được sử dụng để tìm nạp các tập lệnh đó. Vì AJAX đồng bộ chặn mọi thứ khác một cách hiệu quả, nên có thể chắc chắn rằng các tập lệnh và sự kiện thực thi theo đúng thứ tự.


3

Lý do:

Giả sử bạn có một ứng dụng ajax cần nửa tá http tải các dữ liệu khác nhau từ máy chủ trước khi người dùng có thể thực hiện bất kỳ tương tác nào.

Rõ ràng là bạn muốn điều này được kích hoạt từ onload.

Các cuộc gọi đồng bộ hoạt động rất tốt cho điều này mà không có bất kỳ sự phức tạp nào thêm vào mã. Nó là đơn giản và dễ hiểu.

Hạn chế:

Hạn chế duy nhất là trình duyệt của bạn bị khóa cho đến khi tất cả dữ liệu được tải hoặc thời gian chờ xảy ra. Đối với ứng dụng ajax được đề cập, đây không phải là vấn đề nhiều vì ứng dụng sẽ không có giá trị sử dụng cho đến khi tất cả dữ liệu ban đầu được tải.

Thay thế?

Tuy nhiên, nhiều trình duyệt khóa tất cả các cửa sổ / tab khi javascript đang bận trong bất kỳ cửa sổ / tab nào trong số đó, đó là một vấn đề thiết kế trình duyệt ngu ngốc - nhưng kết quả là việc chặn trên mạng có thể chậm là không lịch sự nếu nó ngăn người dùng sử dụng các tab khác trong khi chờ tải trang ajax.

Tuy nhiên, có vẻ như các tính năng đồng bộ đã bị xóa hoặc bị hạn chế khỏi các trình duyệt gần đây. Tôi không chắc đó có phải là do ai đó quyết định rằng họ luôn luôn tồi tệ hay không, hay nếu những người viết trình duyệt đã bối rối trước WC Working Draft về chủ đề này.

http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method có vẻ như (xem phần 4.7.3) bạn không được phép đặt thời gian chờ khi sử dụng chế độ chặn . Tôi thấy có vẻ phản trực giác: Bất cứ khi nào người ta chặn IO, việc đặt thời gian chờ hợp lý là lịch sự, vậy tại sao lại cho phép chặn io mà không phải với thời gian chờ do người dùng chỉ định?

Ý kiến ​​của tôi là chặn IO có vai trò quan trọng trong một số tình huống nhưng phải được thực hiện một cách chính xác. Mặc dù không thể chấp nhận một tab hoặc cửa sổ trình duyệt khóa tất cả các tab hoặc cửa sổ khác, đó là một lỗi thiết kế của trình duyệt. Xấu hổ vì xấu hổ. Nhưng hoàn toàn có thể chấp nhận được trong một số trường hợp một tab hoặc cửa sổ riêng lẻ không phản hồi trong vài giây (tức là sử dụng chặn IO / HTTP GET) trong một số tình huống - ví dụ: khi tải trang, có lẽ rất nhiều dữ liệu cần phải có trước khi bất cứ điều gì có thể được thực hiện. Đôi khi mã chặn được triển khai đúng cách là cách tốt nhất để làm điều đó.

Tất nhiên chức năng tương đương trong trường hợp này có thể được lấy bằng cách sử dụng http get không đồng bộ, nhưng loại thói quen ngốc nghếch nào là bắt buộc?

Tôi đoán tôi sẽ thử một cái gì đó dọc theo những dòng sau:

Khi tải tài liệu, hãy thực hiện như sau: 1: Thiết lập 6 biến cờ "Xong" chung, được khởi tạo thành 0. 2: Thực thi tất cả 6 biến nền được nhận (Giả sử thứ tự không quan trọng)

Sau đó, các lệnh gọi lại hoàn thành cho mỗi trong số 6 http get sẽ đặt cờ "Hoàn thành" tương ứng của chúng. Ngoài ra, mỗi lệnh gọi lại sẽ kiểm tra tất cả các cờ đã hoàn thành khác để xem liệu tất cả 6 HTTP được hoàn thành chưa. Lần gọi lại cuối cùng để hoàn thành, khi thấy rằng tất cả những cái khác đã hoàn thành, sau đó sẽ gọi hàm REAL init, hàm này sau đó sẽ thiết lập mọi thứ, bây giờ tất cả dữ liệu đã được tìm nạp.

Nếu thứ tự tìm nạp quan trọng - hoặc nếu máy chủ web không thể chấp nhận nhiều yêu cầu cùng một lúc - thì bạn sẽ cần một cái gì đó như sau:

Trong onload (), http đầu tiên sẽ được khởi chạy. Trong cuộc gọi lại của nó, cái thứ hai sẽ được khởi chạy. Trong đó là callback, thứ ba - vân vân và vân vân, với mỗi callback sẽ khởi chạy HTTP GET tiếp theo. Khi cái cuối cùng quay trở lại, thì nó sẽ gọi quy trình init () thực.


2

Điều gì xảy ra nếu bạn thực hiện cuộc gọi đồng bộ trong mã sản xuất?

Bầu trời như sụp đổ.

Không nghiêm túc, người dùng không thích một trình duyệt bị khóa.


2
Câu hỏi đặt ra là "tại sao làm điều đó với XMLHttpRequest" không phải là "tại sao làm hay không làm cuộc gọi đồng bộ"
Itay Moav -Malimovka

1
Nếu bạn thêm thời gian chờ hợp lý sẽ không thành vấn đề.
Greg

1
Ông yêu cầu đối với trường hợp sử dụng các cuộc gọi đồng bộ hóa ... Không cho nhược điểm của họ (chúng ta đều biết những bây giờ ...)
Stijn de Witt

người dùng nào? tất cả người dùng có giống nhau không? làm thế nào về các kỹ sư thử nghiệm tại địa phương? ... nên việc truy cập các tập tin của hệ thống tập tin rất ít bị lag ????
user2800679

2

Tôi sử dụng nó để xác thực tên người dùng, trong quá trình kiểm tra tên người dùng đó chưa tồn tại.

Tôi biết sẽ tốt hơn nếu thực hiện điều đó một cách không đồng bộ, nhưng sau đó tôi nên sử dụng một mã khác cho quy tắc xác thực cụ thể này. Tôi giải thích rõ hơn. Thiết lập xác thực của tôi sử dụng một số hàm xác thực, các hàm này trả về true hoặc false, tùy thuộc vào dữ liệu có hợp lệ hay không.

Vì hàm phải trả về nên mình không thể sử dụng kỹ thuật không đồng bộ nên mình chỉ thực hiện đồng bộ như vậy mong máy chủ trả lời kịp thời để không quá chú ý. Nếu tôi sử dụng lệnh gọi lại AJAX, thì tôi sẽ phải xử lý phần còn lại của quá trình thực thi khác với các phương thức xác thực khác.


Một mẹo trong trường hợp như vậy là để cho chức năng xác nhận chỉ kiểm tra một cờ (bắt đầu là false) và chỉ đặt nó thành true hoặc false khi máy chủ phản hồi. thay đổi trường, bạn đặt lại cờ và gọi lại máy chủ.
Stijn de Witt

2

Đôi khi bạn có một hành động phụ thuộc vào người khác. Ví dụ, hành động B chỉ có thể được bắt đầu nếu A kết thúc. Cách tiếp cận đồng bộ thường được sử dụng để tránh các điều kiện đua . Đôi khi sử dụng lệnh gọi đồng bộ là một triển khai đơn giản hơn, sau đó tạo logic phức tạp để kiểm tra mọi trạng thái của lệnh gọi không đồng bộ của bạn phụ thuộc vào nhau.

Vấn đề với cách tiếp cận này là bạn "chặn" trình duyệt của người dùng cho đến khi hành động kết thúc (cho đến khi yêu cầu trả về, kết thúc, tải, v.v.). Vì vậy, hãy cẩn thận khi sử dụng nó.


Câu hỏi đặt ra là "tại sao làm điều đó với XMLHttpRequest" không phải là "tại sao cuộc gọi đồng bộ"
Itay Moav -Malimovka

Bản thân tác giả cho biết "Các cuộc gọi đồng bộ chặn trình duyệt dẫn đến trải nghiệm người dùng tồi tệ." trong một nhận xét, vì vậy mọi người trong chuỗi này đã áp dụng phương pháp "lệnh gọi đồng bộ". Tại sao bạn lại hiểu câu hỏi theo nghĩa đen này nếu bạn thực sự không thể nói chắc chắn tác giả muốn nói gì?
GmonC

2

Tôi sử dụng các lệnh gọi đồng bộ khi phát triển mã - bất cứ điều gì bạn đã làm trong khi yêu cầu đang đi đến và từ máy chủ có thể che khuất nguyên nhân gây ra lỗi.

Khi nó hoạt động, tôi làm cho nó không đồng bộ, nhưng tôi cố gắng đưa vào bộ hẹn giờ hủy bỏ và các lệnh gọi lại thất bại, vì bạn không bao giờ biết ...


2

SYNC vs ASYNC: Sự khác biệt là gì?

Về cơ bản, nó tóm gọn lại điều này:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
});
console.info('Goodbye cruel world!');

Khi doSomethingđồng bộ này sẽ in:

Hello, World!
Got result!
Goodbye cruel world!

Ngược lại, nếu doSomethingkhông đồng bộ , điều này sẽ in:

Hello, World!
Goodbye cruel world!
Got result!

Vì hàm doSomethingđang hoạt động nên nó hoạt động không đồng bộ, nó sẽ trả về trước khi hoàn thành công việc. Vì vậy, chúng tôi chỉ nhận được kết quả sau khi inGoodbye cruel world!

Nếu chúng ta phụ thuộc vào kết quả của một lệnh gọi không đồng bộ, chúng ta cần đặt mã tùy thuộc vào lệnh gọi lại:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
    if (result === 'good') {
        console.info('I feel great!');
    }
    else {
        console.info('Goodbye cruel world!');
    }
});

Do đó, chỉ cần 2 hoặc 3 điều cần diễn ra theo thứ tự thì không có lý do gì để thực hiện chúng một cách đồng bộ (mặc dù mã đồng bộ hóa dễ làm việc hơn đối với hầu hết mọi người).

TẠI SAO SỬ DỤNG XMLHTTPREQUEST SYNCHRONOUS?

Có một số tình huống mà bạn cần kết quả trước khi hàm được gọi hoàn tất. Hãy xem xét tình huống này:

function lives(name) {
    return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');

Giả sử chúng ta không có quyền kiểm soát mã gọi ( console.infođường truyền) và cần thay đổi chức năng livesđể yêu cầu máy chủ ... Không có cách nào chúng ta có thể thực hiện yêu cầu không đồng bộ với máy chủ từ bên trong livesvà vẫn có phản hồi của chúng tôi trước khi liveshoàn tất. Vì vậy, chúng tôi sẽ không biết liệu có nên quay trở lại truehay không false. Cách duy nhất để nhận được kết quả trước khi hàm hoàn thành là thực hiện một yêu cầu đồng bộ.

Như đã Sami Samhuriđề cập trong câu trả lời của anh ấy, một tình huống rất thực tế mà bạn có thể cần câu trả lời cho yêu cầu máy chủ của mình trước khi chức năng của bạn kết thúc là onbeforeunloadsự kiện, vì đó là chức năng cuối cùng từ ứng dụng của bạn sẽ chạy trước khi cửa sổ bị đóng.

TÔI KHÔNG CẦN CUỘC GỌI ĐỒNG BỘ NHƯNG TÔI SỬ DỤNG CHÚNG MỌI LÚC NÀO DỄ DÀNG HƠN

Xin đừng. Các cuộc gọi đồng bộ khóa trình duyệt của bạn và khiến ứng dụng không phản hồi. Nhưng bạn đúng. Mã không đồng bộ khó hơn. Tuy nhiên, có một cách để làm cho nó dễ dàng hơn nhiều. Không dễ dàng như mã đồng bộ, nhưng nó đang đến gần: Promise s.

Đây là một ví dụ: Hai lệnh gọi không đồng bộ đều phải hoàn thành thành công trước khi đoạn mã thứ ba có thể chạy:

var carRented = rentCar().then(function(car){
  gasStation.refuel(car);
});

var hotelBooked = bookHotel().then(function(reservation) {
  reservation.confirm();
});

Promise.all([carRented, hotelBooked]).then(function(){
  // At this point our car is rented and our hotel booked.
  goOnHoliday();
});

Đây là cách bạn sẽ triển khai bookHotel:

function bookHotel() {
  return new Promise(function(resolve, reject){
    if (roomsAvailable()) {
      var reservation = reserveRoom();
      resolve(reservation);
    }
    else {
      reject(new Error('Could not book a reservation. No rooms available.'));
    }
  });
}

Xem thêm: Viết JavaScript tốt hơn với lời hứa .


1
"Vui lòng không. Các cuộc gọi đồng bộ khóa trình duyệt của bạn và khiến ứng dụng không phản hồi" Đây không phải lúc nào cũng là một vấn đề. Hãy tưởng tượng bạn đang thử nghiệm localhost và bạn là một nhà phát triển.
user2800679

2

XMLHttpRequestthường được sử dụng cho các yêu cầu không đồng bộ. Đôi khi (để gỡ lỗi hoặc logic nghiệp vụ cụ thể) bạn muốn thay đổi tất cả / một số lệnh gọi không đồng bộ trong một trang để đồng bộ hóa.

Bạn muốn làm điều đó mà không cần thay đổi mọi thứ trong mã JS của mình. Cờ không đồng bộ / đồng bộ hóa cung cấp cho bạn khả năng đó và nếu được thiết kế đúng cách, bạn chỉ cần thay đổi một dòng trong mã của mình / thay đổi giá trị của một dòng vartrong thời gian thực thi.



1

Tôi vừa gặp phải tình huống trong đó các yêu cầu không đồng bộ cho danh sách các url được gọi liên tiếp bằng forEach (và vòng lặp for) sẽ khiến các yêu cầu còn lại bị hủy. Tôi đã chuyển sang đồng bộ và chúng hoạt động như dự định.


1

Sử dụng các yêu cầu HTTP đồng bộ là một thực tế phổ biến trong kinh doanh quảng cáo trên điện thoại di động.

Các công ty (hay còn gọi là "Nhà xuất bản") xây dựng ứng dụng thường chạy quảng cáo để tạo doanh thu. Đối với điều này, họ cài đặt SDK quảng cáo vào ứng dụng của họ. Nhiều tồn tại (MoPub, Ogury, TapJob, AppNext, Google Ads AdMob).

Các SDK này sẽ phân phát quảng cáo trong chế độ xem web.

Khi phân phát quảng cáo cho người dùng, đó phải là một trải nghiệm mượt mà, đặc biệt là khi phát video. Không có bộ đệm hoặc tải bất kỳ lúc nào.

Để giải quyết điều này precachingđược sử dụng. Nơi phương tiện (hình ảnh / video / v.v.) được tải đồng bộ trong nền của chế độ xem web.

Tại sao không làm nó không đồng bộ?

  1. Đây là một phần của tiêu chuẩn được chấp nhận trên toàn cầu
  2. SDK sẽ lắng nghe onloadsự kiện để biết khi nào quảng cáo "sẵn sàng" được phân phát cho người dùng

Với việc ngừng sử dụng XMLHttpRequests đồng bộ , doanh nghiệp quảng cáo rất có thể sẽ bị buộc phải thay đổi tiêu chuẩn trong tương lai trừ khi có thể xác định được cách khác.


0

XHR đồng bộ có thể rất hữu ích cho việc phát triển công cụ và / hoặc khung nội bộ (phi sản xuất). Hãy tưởng tượng, chẳng hạn, bạn muốn tải đồng bộ thư viện mã trong lần truy cập đầu tiên, như thế này:

get draw() 
{
    if (!_draw)
    {
       let file;
       switch(config.option)
       {
           case 'svg':
              file = 'svgdraw.js';
              break;
           case 'canvas':
              file = 'canvasdraw.js';
              break;
           default:
              file = 'webgldraw.js';
       }

       var request = new XMLHttpRequest();
       request.open('GET', file, false);
       request.send(null);
       _draw = eval(request.responseText);
    }

    return _draw;
}

Trước khi bạn rơi vào tình trạng mù mịt và khơi dậy một cách mù quáng cái ác của eval, hãy nhớ rằng điều này chỉ dành cho thử nghiệm cục bộ. Đối với các bản dựng sản xuất, _draw sẽ được thiết lập.

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

foo.drawLib.draw.something(); //loaded on demand

Đây chỉ là một ví dụ về điều gì đó sẽ không thể thực hiện được nếu không có XHR đồng bộ. Bạn có thể tải thư viện này lên trước, có, hoặc thực hiện một lời hứa / gọi lại, nhưng bạn không thể tải lib một cách đồng bộ mà không đồng bộ XHR. Hãy nghĩ xem loại thứ này có thể làm sạch mã của bạn đến mức nào ...

Giới hạn đối với những gì bạn có thể làm với điều này đối với công cụ và khuôn khổ (chạy cục bộ) chỉ bị giới hạn bởi trí tưởng tượng của bạn. Mặc dù vậy, có vẻ như trí tưởng tượng có một chút hạn chế trong thế giới JavaScript.


-1

Đây là một lý do chính đáng. Sau đó, tôi muốn thực hiện một yêu cầu http, tùy thuộc vào kết quả, hãy gọi click () trên loại đầu vào = tệp. Điều này không thể xảy ra với xhr hoặc tìm nạp không đồng bộ. Lệnh gọi lại làm mất ngữ cảnh "hành động của người dùng", vì vậy lệnh gọi click () bị bỏ qua. Xhr đồng bộ đã lưu thịt xông khói của tôi.

onclick(event){
    //here I can, but I don't want to.
    //document.getElementById("myFileInput").click();
    fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
    .then((response)=>response.json())
    .then(function (validResult) {
        if (validResult.success) {
            //here, I can't.
            document.getElementById("myFileInput").click();
        }
    });
}

lưu nó vào một var
Es Noguera
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.