2013-07-19 38 views
12

Tôi mới trong nút và cố gắng sử dụng các lợi thế hành vi không đồng bộ và sự kiện trong nút. Tôi sử dụng để hiểu từ nút, tất cả mọi thứ mà xử lý với đối tượng sự kiện, nó sẽ được thực thi async.
Sau đó, tôi đã cố gắng này, hãy xem xét đoạn mã sau:viết chức năng không đồng bộ với EventEmitter

var events = require("events"); 

var event = new events.EventEmitter(); 


event.on("work", function() { 

    for (var i = 0; i <= 10; i++) { 
     console.log("I do my work " + i); 
    } 

    event.emit("done"); 
}); 

var async = function (cb) { 

    event.on("done", cb); 
    event.emit("work"); 
    for (var i = 0; i <= 10; i++) { 
     console.log("Async " + i); 
    } 
} 


async(function() { 
    console.log("I am done callback!"); 
}); 

Đây là thực async? Theo tôi thì không! Tại sao, bởi vì tôi đã đọc câu này nhiều:

Sự kiện được kích hoạt, hãy thực hiện một việc gì đó và sau đó khi bạn hoàn thành nó, hãy đến số và cho tôi biết.

Giống như kịch bản nhà hàng thức ăn nhanh. Nhưng đoạn mã trên, khi công việc sự kiện sẽ bị sa thải, trình tự sau đây sẽ xảy ra:

  1. đi vào callback
  2. cho qua vòng lặp
  3. ra tôi làm công việc của tôi n
  4. bắn sự kiện thực hiện
  5. đầu ra Tôi đã gọi lại xong!
  6. đầu ra Async n

lý do tại sao tôi gọi lại! sẽ ra trước Async n? Tại sao ở đây không giống như kịch bản nhà hàng thức ăn nhanh, như

sự kiện công việc là bắn, đi và làm bạn công cụ và trở lại khi bạn thực hiện, trong khi đó tôi sẽ ra Async n

này là tôi được sử dụng để hiểu về hành vi theo hướng sự kiện và async trong nút. Nhưng bây giờ tôi rất bối rối. Tôi biết, javascript hoạt động trên một chuỗi. Làm thế nào tôi có thể viết một chức năng async với bộ phát sự kiện? Nhưng tôi nghĩ là không thể, bởi vì khi tôi phát ra một sự kiện, nó sẽ ngay lập tức thực hiện xử lý.

Trả lời

18

Tôi đã từng hiểu từ nút, mọi thứ xử lý với đối tượng Event , nó sẽ được thực thi không đồng bộ.

Điều này không đúng. Sự kiện là đồng bộ. Khi bạn thêm một người biết lắng nghe, bạn chỉ cần tiết kiệm gọi lại trong một đối tượng:

this._events[type].push(listener); 

Khi bạn phát ra một sự kiện, bạn chỉ cần lặp lại một mảng và kêu gọi mỗi người nghe:

for (i = 0; i < len; i++) 
     listeners[i].apply(this, args); 

Nguồn mã: https://github.com/joyent/node/blob/master/lib/events.js

Đây là thực thi không đồng bộ? Theo tôi thì không!

Bạn là chính xác. Sẽ không đồng bộ nếu bạn gọi bất kỳ chức năng I/O nào hoặc sử dụng setImmediate, nextTick hoặc hẹn giờ — nếu không, nó sẽ đồng bộ.Một mã đồng bộ được viết asynchrously không chuyển đổi nó thành một mã asynchrous.

lý do tôi gọi lại! sẽ ra trước Async n?

Bởi vì khi bạn nhận được "thực hiện" gọi lại bạn gọi đến "cb":

event.on("done", cb); 

Khi cb lợi nhuận, các "Async n" vòng lặp được thực thi.

Làm cách nào để viết chức năng async với trình phát sự kiện?

Sử dụng setImmediate hoặc process.nextTick.

Nếu bạn muốn trì hoãn việc thực hiện vòng lặp "Tôi làm việc của tôi", bạn có thể quấn dòng events.emit ("work") bằng nextTick.

var events = require("events"); 

var event = new events.EventEmitter(); 


event.on("work", function() { 

    for (var i = 0; i <= 10; i++) { 
     console.log("I do my work " + i); 
    } 

    event.emit("done"); 
}); 

var async = function (cb) { 

    event.on("done", cb); 
    process.nextTick (function() {   //<----- 
     event.emit("work"); 
    });          //<----- 
    for (var i = 0; i <= 10; i++) { 
     console.log("Async " + i); 
    } 
} 


async(function() { 
    console.log("I am done callback!"); 
}); 

này sẽ in:

Async 0 
Async 1 
Async 2 
Async 3 
Async 4 
Async 5 
Async 6 
Async 7 
Async 8 
Async 9 
Async 10 
I do my work 0 
I do my work 1 
I do my work 2 
I do my work 3 
I do my work 4 
I do my work 5 
I do my work 6 
I do my work 7 
I do my work 8 
I do my work 9 
I do my work 10 
I am done callback! 
+0

Vòng lặp Sự kiện này sẽ được thực hiện một lần nữa, sau khi các mã trong ngăn xếp đã được hoàn thành. Ví dụ, tôi có 3 dòng mã. Đầu tiên là process.nextTick (dosomething) và chỉ console.log ("something") ;. Sau đó vòng lặp sự kiện sẽ được thực thi ngay? Và ở đầu vòng lặp này, hàm gọi lại đã đăng ký trong process.nextTick() sẽ được thực thi. Đúng? –

+0

xem mã sau đây, khi tôi gọi/test1 và trong trình duyệt/test2 khác, cần một thời gian dài để nhận phản hồi trên/test2, đối với tôi nó giống như/test1 block/test2 var express = require ('express'); var app = express(); app.get ('/', chức năng (req, res) { res.send ('Hello World'); }); app.get ('/ test1', function (req, res) { \t \t for (var i = 0; i <= 100.000.000.000; i ++) { \t \t \t} res.send ('Các vòng lặp kết thúc '); }); app.get ('/ test2', chức năng (req, res) { res.send ('Không có vòng lặp'); }); app.listen (3000); console.log ('Express bắt đầu trên cổng 3000'); –

+2

/test1 đang "chặn" vòng lặp sự kiện. Đó là lý do tại sao nút không dành cho các tác vụ cpu chuyên sâu. Bạn có thể sinh ra một quy trình mới và làm những công việc này. Đọc bài viết này để hiểu đầy đủ về sự tương tranh trong nút: http://neilk.net/blog/2013/04/30/why-you-should-use-nodejs-for-CPU-bound-tasks/ –

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