Hướng dẫn is javascript is synchronous or asynchronous? - javascript là đồng bộ hay không đồng bộ?

Học cách làm việc trong một môi trường duy nhất

Là người, chúng tôi thích cấu trúc. Chúng tôi thích các danh mục, mô tả và đặt mọi thứ chúng tôi biết vào các hộp nhỏ gọn gàng. Đây là lý do tại sao tôi thấy JavaScript rất khó hiểu lúc đầu. Nó là một kịch bản hay ngôn ngữ lập trình? Nó được sử dụng ở mặt trước hay mặt sau?

Điều tuyệt vời (đọc: khủng khiếp) về JavaScript là hầu hết thời gian, nó có một chút của cả hai. JavaScript đã phát triển rất nhiều trong những năm qua đến nỗi nó khó phân loại. Hôm nay, tôi sẽ đi sâu vào việc JavaScript có đồng bộ hay không đồng bộ và quy trình làm việc trông như thế nào dưới mui xe.

JavaScript là đồng bộ

Spoiler: Tại cơ sở của nó, JavaScript là một ngôn ngữ đồng bộ, chặn, đơn luồng. Điều đó chỉ có nghĩa là chỉ có một hoạt động có thể được tiến hành tại một thời điểm. Đó không phải là toàn bộ câu chuyện, mặc dù!

Hình ảnh của Aleks Shineleva

Điều gì sẽ xảy ra nếu bạn phải thực hiện một yêu cầu cơ sở dữ liệu đắt tiền? Bạn không muốn twiddling ngón tay cái của bạn trong khi PG và Postgres lấy 800 bài hát bạn cần cho thư viện nhạc của mình. Mã đồng bộ làm cho cuộc sống của một lập trình viên rất khó khăn, vì vậy cộng đồng JavaScript đã phát triển một số cách giải quyết tuyệt vời.

Khi bạn nghe mọi người nói rằng JavaScript là một ngôn ngữ không đồng bộ, điều họ có nghĩa là bạn có thể điều khiển JavaScript để hành xử theo cách không đồng bộ. Nó không nướng vào, nhưng nó có thể! Dưới đây là một vài cách để thực hiện điều đó:

Các cuộc gọi lại không đồng bộ

Giải pháp sớm nhất và đơn giản nhất để bị mắc kẹt trong thế giới đồng bộ đang sử dụng các cuộc gọi lại không đồng bộ (nghĩ setTimeout()).

Hãy sử dụng yêu cầu cơ sở dữ liệu làm ví dụ: các cuộc gọi lại không đồng bộ cho phép bạn gọi chức năng gọi lại gửi yêu cầu cơ sở dữ liệu (và bất kỳ cuộc gọi lại lồng nào khác) cho ứng dụng của bạn, nơi nó chờ phản hồi từ cơ sở dữ liệu, giải phóng phần còn lại của phần còn lại của Mã của bạn để tiếp tục chạy.

Hình ảnh của Aleks Shineleva

Điều gì sẽ xảy ra nếu bạn phải thực hiện một yêu cầu cơ sở dữ liệu đắt tiền? Bạn không muốn twiddling ngón tay cái của bạn trong khi PG và Postgres lấy 800 bài hát bạn cần cho thư viện nhạc của mình. Mã đồng bộ làm cho cuộc sống của một lập trình viên rất khó khăn, vì vậy cộng đồng JavaScript đã phát triển một số cách giải quyết tuyệt vời.

Khi bạn nghe mọi người nói rằng JavaScript là một ngôn ngữ không đồng bộ, điều họ có nghĩa là bạn có thể điều khiển JavaScript để hành xử theo cách không đồng bộ. Nó không nướng vào, nhưng nó có thể! Dưới đây là một vài cách để thực hiện điều đó:

Các cuộc gọi lại không đồng bộ

Giải pháp sớm nhất và đơn giản nhất để bị mắc kẹt trong thế giới đồng bộ đang sử dụng các cuộc gọi lại không đồng bộ (nghĩ setTimeout()).

Hãy sử dụng yêu cầu cơ sở dữ liệu làm ví dụ: các cuộc gọi lại không đồng bộ cho phép bạn gọi chức năng gọi lại gửi yêu cầu cơ sở dữ liệu (và bất kỳ cuộc gọi lại lồng nào khác) cho ứng dụng của bạn, nơi nó chờ phản hồi từ cơ sở dữ liệu, giải phóng phần còn lại của phần còn lại của Mã của bạn để tiếp tục chạy.

Khi yêu cầu cơ sở dữ liệu hoàn tất, kết quả (và bất kỳ mã lồng nhau nào khác) sẽ được gửi đến hàng đợi và sau đó được xử lý thông qua vòng lặp sự kiện.

Trong sơ đồ ở đây, bạn có thể thấy điều này khác với mã đồng bộ như thế nào. Chức năng C, cùng với E, F và G đều được gửi đến trình duyệt, hàng đợi và vòng lặp sự kiện.

Nếu bạn muốn một lời giải thích rõ ràng, tuyệt vời về quá trình này, hãy xem cuộc biểu tình này của Philip Roberts.

Trong khi đây là một giải pháp tuyệt vời, nó để lại một cái gì đó mong muốn. Vì bạn có thể dự đoán chính xác khi nào chức năng C sẽ giải quyết, bạn phải làm tổ tất cả các chức năng phụ thuộc trong đó. Điều này trở nên lộn xộn nhanh chóng và dẫn đến địa ngục gọi lại khét tiếng mà không ai muốn đối phó. Chính môi trường này đã truyền cảm hứng cho lời hứa.

Hứa hẹn

Async/Await

Để đối phó với địa ngục gọi lại, các thư viện như Bluebird hoặc Q cho phép các lập trình viên làm sạch cú pháp của họ và viết mã hoạt động không đồng bộ nhưng trông đồng bộ. Điều này dẫn đến mã dễ đọc hơn và nhanh hơn để chạy.

Hình ảnh của Aleks Shineleva

  • Với một lời hứa, thay vì kết hợp tất cả các phụ thuộc vào một khối mã và gửi toàn bộ điều đến trình duyệt, chúng tôi có thể tách chúng ra.
  • Chúng ta có thể gửi cuộc gọi lại không đồng bộ (chức năng C) đến trình duyệt và sử dụng .then() để giữ tất cả các phụ thuộc khác (E, F và G) sang một bên, chỉ chạy chúng một khi chức năng C trả về và chạy.
  • Điều này cho phép chúng tôi mã hóa theo cách mô -đun hơn, dễ đọc hơn, trong khi vẫn đạt được những lợi ích của lập trình không đồng bộ.

Những lời hứa thật tuyệt vời - trên thực tế, ES6 đã đưa chúng vào ngôn ngữ như một tiêu chuẩn. Nhưng sử dụng những lời hứa vẫn còn lại mã không đồng bộ cảm thấy hơi mạnh mẽ, vì vậy bây giờ chúng tôi có Async/chờ đợi tuyệt đẹp và chờ đợi để giúp chúng tôi!

Có toàn bộ các bài đăng trên blog và (tôi chắc chắn) các cuốn sách được viết về Async/Await, vì vậy tôi sẽ không đi sâu vào nó quá sâu, nhưng đủ để nói rằng Async/đang chờ đợi cho phép bạn:

Tiếp tục sử dụng lời hứa

Sự định nghĩa

Thuật ngữ "không đồng bộ" có thể được sử dụng trong các ý nghĩa hơi khác nhau, dẫn đến những câu trả lời dường như mâu thuẫn ở đây, trong khi chúng thực sự không. Wikipedia trên sự không đồng bộ có định nghĩa này:

Sự không đồng bộ, trong lập trình máy tính, đề cập đến sự xuất hiện của các sự kiện độc lập với luồng chương trình chính và các cách để đối phó với các sự kiện đó. Đây có thể là các sự kiện "bên ngoài" như sự xuất hiện của tín hiệu hoặc hành động được xúi giục bởi một chương trình diễn ra đồng thời với việc thực hiện chương trình, mà không cần phải chờ chương trình để chờ kết quả.

Mã không phải là JavaScript có thể xếp hàng các sự kiện "bên ngoài" như vậy cho một số hàng đợi sự kiện của JavaScript. Nhưng đó là xa như nó đi.

Không có quyền ưu tiên

Không có sự gián đoạn bên ngoài của việc chạy mã JavaScript để thực thi một số mã JavaScript khác trong tập lệnh của bạn. Các phần của JavaScript được thực hiện lần lượt và thứ tự được xác định theo thứ tự các sự kiện trong mỗi hàng đợi sự kiện và mức độ ưu tiên của các hàng đợi đó.

Chẳng hạn, bạn có thể hoàn toàn chắc chắn rằng không có JavaScript nào khác (trong cùng một tập lệnh) sẽ thực hiện trong khi phần mã sau đang thực thi:

let a = [1, 4, 15, 7, 2];
let sum = 0;
for (let i = 0; i < a.length; i++) {
    sum += a[i];
}

Nói cách khác, không có sự ưu tiên trong JavaScript. Bất cứ điều gì có thể có trong hàng đợi sự kiện, việc xử lý các sự kiện đó sẽ phải đợi cho đến khi đoạn mã đó chạy để hoàn thành. Thông số kỹ thuật của Ecmascript cho biết trong phần 8.4 HÀNG HÀNG VÀ CÔNG VIỆC HÀNG ĐẦU:

Việc thực thi công việc chỉ có thể được bắt đầu khi không có ngữ cảnh thực thi đang chạy và ngăn xếp bối cảnh thực thi trống rỗng.

Ví dụ về sự không đồng bộ

Như những người khác đã viết, có một số tình huống mà sự không đồng bộ xuất hiện trong JavaScript và nó luôn liên quan đến hàng đợi sự kiện, điều này chỉ có thể dẫn đến việc thực thi JavaScript khi không có mã JavaScript thực thi:

  • setTimeout(): Tác nhân (ví dụ: Trình duyệt) sẽ đưa một sự kiện vào hàng đợi sự kiện khi hết thời gian chờ. Việc giám sát thời gian và việc đặt sự kiện trong hàng đợi xảy ra bằng mã không phải là JavaScript và do đó bạn có thể tưởng tượng điều này xảy ra song song với việc thực hiện tiềm năng của một số mã JavaScript. Nhưng cuộc gọi lại được cung cấp cho setTimeout chỉ có thể thực thi khi mã JavaScript hiện đang thực hiện đã hoàn thành và hàng đợi sự kiện thích hợp đang được đọc.

  • fetch(): Tác nhân sẽ sử dụng các chức năng HĐH để thực hiện yêu cầu HTTP và giám sát bất kỳ phản hồi đến nào. Một lần nữa, nhiệm vụ không phải là JavaScript này có thể chạy song song với một số mã JavaScript vẫn đang thực thi. Nhưng quy trình giải quyết lời hứa, sẽ giải quyết lời hứa được trả lại bởi fetch(), chỉ có thể thực hiện khi JavaScript hiện đang thực hiện đã hoàn thành.

  • requestAnimationFrame(): Công cụ kết xuất của trình duyệt (không phải là JavaScript) sẽ đặt một sự kiện trong hàng đợi JavaScript khi nó sẵn sàng thực hiện thao tác sơn. Khi sự kiện JavaScript được xử lý, chức năng gọi lại được thực thi.

  • queueMicrotask(): Ngay lập tức đặt một sự kiện trong hàng đợi microtask. Cuộc gọi lại sẽ được thực hiện khi ngăn xếp cuộc gọi trống và sự kiện đó được tiêu thụ.

Có nhiều ví dụ hơn, nhưng tất cả các chức năng này được cung cấp bởi môi trường chủ, không phải bởi Core Ecmascript. Với Core Ecmascript, bạn có thể đồng bộ đặt một sự kiện vào hàng đợi công việc hứa hẹn với Promise.resolve().

Cấu trúc ngôn ngữ

Ecmascript cung cấp một số cấu trúc ngôn ngữ để hỗ trợ mẫu không đồng bộ, chẳng hạn như setTimeout()0, setTimeout()1, setTimeout()2. Nhưng hãy để không có sai lầm: Không có mã JavaScript sẽ bị gián đoạn bởi một sự kiện bên ngoài. "Sự gián đoạn" mà ____10 và setTimeout()2 dường như cung cấp chỉ là một cách được kiểm soát, được xác định trước để quay lại từ một cuộc gọi chức năng và khôi phục bối cảnh thực thi của nó sau này, theo mã JS (trong trường hợp ____10) hoặc hàng đợi sự kiện (trong trường hợp của setTimeout()2).

Xử lý sự kiện DOM

Khi mã JavaScript truy cập API DOM, trong một số trường hợp, điều này có thể tạo API DOM kích hoạt một hoặc nhiều thông báo đồng bộ. Và nếu mã của bạn có một người xử lý sự kiện lắng nghe điều đó, nó sẽ được gọi.

Điều này có thể xuất hiện dưới dạng đồng thời ưu tiên, nhưng không phải: đó là mã JavaScript bắt đầu cuộc gọi API và do đó kiểm soát rằng API có thể thực hiện một số thứ .

Trong các trường hợp khác, API DOM sẽ chỉ gửi một sự kiện trong hàng đợi sự kiện thích hợp và JavaScript sẽ nhận nó một khi ngăn xếp cuộc gọi đã được làm trống.

Xem các sự kiện đồng bộ và không đồng bộ

Là JavaScript đồng bộ và không đồng bộ?

JavaScript là spoiler đồng bộ: Tại cơ sở của nó, JavaScript là một ngôn ngữ đồng bộ, chặn, đơn luồng. Điều đó chỉ có nghĩa là chỉ có một hoạt động có thể được tiến hành tại một thời điểm. Đó không phải là toàn bộ câu chuyện, mặc dù! Spoiler: at its base, JavaScript is a synchronous, blocking, single-threaded language. That just means that only one operation can be in progress at a time. That's not the entire story, though!

Là JavaScript hứa hẹn đồng bộ hay không đồng bộ?

Một lời hứa được sử dụng để xử lý kết quả không đồng bộ của một hoạt động.JavaScript được thiết kế để không chờ một khối mã không đồng bộ để thực hiện hoàn toàn trước khi các phần đồng bộ khác của mã có thể chạy.Với những lời hứa, chúng tôi có thể trì hoãn việc thực thi một khối mã cho đến khi yêu cầu Async được hoàn thành.asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.

Tại sao JavaScript không đồng bộ?

Chà, JavaScript đồng bộ, nó là một ngôn ngữ đồng bộ, đơn.Bởi vì nó có một luồng duy nhất đó là lý do tại sao nó chỉ có thể thực thi một lệnh tại một thời điểm và các lệnh khác cần phải chờ thực thi trước khi lệnh chạy thực thi.Và thuật ngữ đồng bộ có nghĩa là một lần.Because it has a single thread that's why it can only execute one command at a time and the other commands need to wait for executing before the running command executes. And the term synchronous means one at a time.

Chức năng JavaScript không đồng bộ?

Đồng bộ vs không đồng bộ theo mặc định, JavaScript là một ngôn ngữ lập trình ren đồng bộ, đơn.Điều này có nghĩa là các hướng dẫn chỉ có thể chạy lần lượt, và không song song.By default, JavaScript is a synchronous, single threaded programming language. This means that instructions can only run one after another, and not in parallel.