2012-02-20 37 views
9

Hiểu biết mới về Node là nếu tôi viết lại mã đồng bộ hoặc mã nội tuyến, để sử dụng các hàm/gọi lại, tôi có thể đảm bảo rằng mã của tôi không bị chặn. Tôi rất tò mò về cách thức hoạt động này về mặt ngăn xếp sự kiện. Ví dụ đơn giản từ đây: Don't understand the callback - Stackoverflow là điều này sẽ chặn:Tại sao chức năng và gọi lại không bị chặn trong Node.JS?

var post = db.query("select * from posts where id = 1"); 
doSomethingWithPost(post) 
doSomethingElse(); 

Trong khi này wont:

callback = function(post){ 
doSomethingWithPost(post) 
} 

db.query("select * from posts where id = 1",callback); 
doSomethingElse(); 

Ok, tôi hiểu rằng chúng tôi nên sử dụng callbacks. Nhưng về mặt sự kiện, tại sao nó lại hoạt động? Javascript là một chuỗi duy nhất .. trong dòng ví dụ đầu tiên, sử dụng một hoạt động I/O đắt tiền và chặn. Dòng 2 không thể thực hiện cho đến khi một dòng được thực hiện. Đây có phải là vì dòng 2 yêu cầu thông tin từ dòng 1 không? Hoặc là bởi vì các sự kiện I/O chỉ đơn giản là chặn các hoạt động có nghĩa là chúng chiếm quyền kiểm soát và không trả lại cho đến khi ...

Trong ví dụ thứ hai, I/O đắt tiền đã được chuyển thành một hàm, và bây giờ chúng ta có chức năng gọi lại. Chắc chắn cuộc gọi lại không thể thực hiện cho đến khi I/O được thực hiện .. Điều này sẽ không thay đổi. Vì vậy, sự khác biệt về lượng thời gian cần thiết để thực hiện giữa một và hai phải chủ yếu là những gì sẽ xảy ra nếu một yêu cầu thứ hai nhấn vào máy chủ.

Nếu yêu cầu thứ hai nhấn một ví dụ, nó sẽ không thể xử lý cho đến khi yêu cầu 1 được thực hiện vì hoạt động chặn .. nhưng trong ví dụ hai .. di chuyển các hoạt động vào các chức năng tự động sinh ra các tiến trình con hoặc hành động như đa luồng? Nếu Javscript là đơn luồng này vẫn sẽ gây ra vấn đề, trừ khi có một số cách xử lý song song .. Có một hàm/callback chỉ đảm bảo là không chặn NẾU chúng ta sử dụng các kỹ thuật không chặn như các tiến trình con, v.v. .

Trả lời

19

Hãy tưởng tượng bạn đang điều hành máy tính tiền trong tiệm bánh. Bạn xử lý khách hàng của bạn liên tục và đồng bộ, như thế này:

  1. Hãy để
  2. Nói với thợ làm bánh để nướng bánh mì
  3. Chờ cho đến khi bánh mì được nướng
  4. phí tiền
  5. Cung cấp bánh mì
  6. GOTO 1 - khách hàng tiếp theo

Điều đó sẽ rất chậm. Bây giờ, hãy thử thay vì để có những đơn đặt hàng liên tục, nhưng xử lý khách hàng của bạn không đồng bộ:

  1. Hãy để
  2. biết chính xác làm bánh để nướng bánh mì, và thông báo cho bạn khi hoàn tất. Khi được thông báo:
    1. phí tiền
    2. Cung cấp bánh mì
  3. GOTO 1 - khách hàng tiếp theo

UPDATE: tôi tái cơ cấu trên, vì vậy nó gần giống với hơn một callback. Bạn, nhân viên thu ngân, sẽ đạt bước 3 ngay lập tức sau khi ra lệnh cho người làm bánh. Bạn sẽ đạt bước 2.1 khi người làm bánh thông báo cho bạn rằng bánh mì đã sẵn sàng.

Bằng cách này, bạn sẽ vẫn phân phối nhiều bánh mì - bạn chỉ có thể bán nhiều bánh mì như bánh của bạn có thể nướng. Nhưng bạn có thể đối phó với khách hàng của bạn một cách hiệu quả hơn, bởi vì thay vì nhàn rỗi chờ đợi cho một đơn đặt hàng để trở lại, bạn bắt đầu xử lý các khách hàng tiếp theo.

Bây giờ, bạn có thể đi tất cả các loại ưa thích về điều này, và tính tiền trả trước, và nói với khách hàng để lấy bánh mì ở đầu kia của bàn, hoặc một cái gì đó như thế. Tôi nghĩ rằng Starbucks là khá "evented" theo cách này. Nhân viên thu ngân nhận đơn đặt hàng, phát hành một số yêu cầu về công cụ và yêu cầu khách hàng đợi cho đến khi mọi thứ đang đứng trong khu vực đón. Siêu hiệu quả.

Bây giờ, hãy tưởng tượng rằng bạn của bạn bắt đầu điều hành một máy tính tiền khác. Anh ta theo ví dụ không đồng bộ của bạn. Bạn có thể xử lý nhiều khách hàng hơn, thậm chí nhanh hơn! Lưu ý rằng điều duy nhất bạn phải làm là đưa bạn mình đến đó và cho anh ta công việc của bạn.

Bạn và bạn của bạn là hai vòng lặp sự kiện đơn luồng chạy song song. Điều này tương tự với hai quá trình node.js nhận yêu cầu. Bạn không cần phải phức tạp gì để song song điều này, bạn chỉ cần chạy thêm một vòng lặp sự kiện.

Vì vậy, không, "chuyển hoạt động thành các hàm" không "tự động sinh ra các tiến trình con". Họ giống như báo động - khi điều này kết thúc, hãy thông báo cho tôi và để tôi nhận vào thời điểm này, "điểm này" là mã trong cuộc gọi lại của bạn. Nhưng cuộc gọi lại sẽ vẫn được thực thi trong cùng một tiến trình và cùng một luồng.

Hiện tại, node.js cũng hoạt động một nhóm luồng nội bộ cho IO. Điều này là trừu tượng xa bạn: Để tiếp tục tương tự bánh, hãy nói rằng bạn có một "thợ làm bánh" của người làm bánh - cho bạn, đứng ở máy tính tiền, bạn không cần phải biết về điều này. Bạn chỉ cần cung cấp cho họ thứ tự ("một ổ bánh mì chua") và giao hàng đó khi bạn được thông báo rằng nó đã hoàn tất. Nhưng các thợ làm bánh đang nướng bánh mì song song, trong "baker pool" của riêng họ.

+1

Cảm ơn sự tương tự tuyệt vời. Để làm rõ thêm. Trong ví dụ này một nhân viên thu ngân nhận một đơn đặt hàng và đưa nó trở lại nhà bếp, sau đó anh ta có thể đi và xử lý một đơn đặt hàng khác. Bây giờ người đặt hàng ở đây là chức năng máy chủ chính .. và nhà bếp là tất cả các chức năng được ủy quyền với các cuộc gọi lại của riêng họ. Nếu chức năng máy chủ đại biểu cho một chức năng và đưa cho họ một cuộc gọi lại và nói .. lấy lại cho tôi khi thực hiện .. Nếu nhà bếp không được đưa ra một phương tiện sinh sản một quá trình con .. nó sẽ không vẫn chặn cho đến khi gọi lại đã được gửi? – Inc1982

+0

Nhà bếp có hồ bơi ren bên trong. Vì vậy, nó sẽ có một số chủ đề để phân phối các nhiệm vụ. Nhưng điều này được tóm tắt từ bạn trong Node.js và không có điều nào trong số đó được thực thi trong vòng lặp sự kiện của bạn, vì vậy nó sẽ không ảnh hưởng đến mã của bạn chút nào. Nếu bạn thực hiện một số phép tính chuyên sâu của CPU trong mã của riêng bạn, điều đó sẽ chặn _ toàn bộ vòng lặp sự kiện_ (như, giả sử nhân viên thu ngân quyết định nướng một trong các ổ bánh - trong thời gian này, anh ta không thể lấy bất kỳ đơn hàng mới nào). –

+1

Bạn có nói rằng đối với một nút chức năng/callback chuẩn có thể sử dụng một pool thread bên trong để đảm bảo hiệu suất không đồng bộ nhưng đối với một cuộc gọi đắt tiền, chúng ta sẽ cần thiết lập một nhân viên như những gì exec sẽ làm gì? Nếu vậy, làm cách nào tôi biết ngưỡng 'đắt tiền'? Điều đó dường như là một điểm then chốt sau đó. – Inc1982

3

Tôi không giỏi tiếng Anh, vì vậy tôi không thể hiểu ý nghĩa của bạn. Nhưng tôi có thể nói rằng 'đa luồng' và 'không đồng bộ' tương tự nhau nhưng khác nhau. Thậm chí nếu chuỗi đơn có thể giống như 'không đồng bộ'.

This document không dành cho nút (nó dành cho khung không đồng bộ python "xoắn") nhưng có thể hữu ích cho bạn.

xin lỗi vì tiếng Anh kém của tôi.

+0

Đây là một tài liệu tuyệt vời mà bạn đã cung cấp, cảm ơn bạn rất nhiều! Rất rõ ràng. – Inc1982

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