2011-08-01 45 views
98

Tôi đã cố gắng nghiên cứu về cách viết chính xác các hàm không đồng bộ. Sau khi rất nhiều cày qua rất nhiều tài liệu, nó vẫn chưa rõ ràng với tôi.Cách viết các hàm không đồng bộ cho Node.js

Làm cách nào để viết các hàm không đồng bộ cho Nút? Làm cách nào để triển khai sự kiện xử lý lỗi chính xác?

Một cách khác để đặt câu hỏi của tôi là: Làm cách nào để diễn giải chức năng sau?

var async_function = function(val, callback){ 
    process.nextTick(function(){ 
     callback(val); 
    }); 
}; 

Ngoài ra, tôi tìm thấy this question on SO ("Làm thế nào để tạo một hàm không đồng bộ non-blocking trong Node.js?") Thú vị. Tôi không cảm thấy nó đã được trả lời.

+13

Đó là lý do tôi hỏi. Nó không rõ ràng với tôi như thế nào các chức năng này là bất kỳ khác nhau. – Kriem

+0

Tôi khuyên bạn nên xem 'setTimeout' và 'setInterval' trong trình duyệt yêu thích của bạn và chơi với chúng. Hoặc gọi lại ajax (có thể là điều gần gũi nhất với trải nghiệm nút) hoặc trình xử lý sự kiện cho những thứ bạn quen thuộc với các sự kiện nhấp và tải. Mô hình không đồng bộ tồn tại trong trình duyệt và chúng giống hệt nhau trong nút. – davin

+0

@davin - Đoán tôi không hoàn toàn hiểu được mô hình không đồng bộ sau đó. – Kriem

Trả lời

77

Có vẻ như bạn đang nhầm lẫn IO không đồng bộ với các hàm không đồng bộ. node.js sử dụng IO không chặn không đồng bộ vì không chặn IO là tốt hơn. Cách tốt nhất để hiểu nó là đi xem một số video của ryan dahl.

Làm cách nào để viết chức năng không đồng bộ cho nút?

Chỉ cần viết chức năng bình thường, sự khác biệt duy nhất là chúng không được thực thi ngay lập tức mà được chuyển qua như gọi lại.

Làm thế nào tôi nên thực hiện sự kiện lỗi xử lý một cách chính xác

chung API cung cấp cho bạn một callback với err như là đối số đầu tiên. Ví dụ:

database.query('something', function(err, result) { 
    if (err) handle(err); 
    doSomething(result); 
}); 

Là mẫu chung.

Một mẫu phổ biến khác là on('error'). Ví dụ

process.on('uncaughtException', function (err) { 
    console.log('Caught exception: ' + err); 
}); 

Edit:

var async_function = function(val, callback){ 
    process.nextTick(function(){ 
     callback(val); 
    }); 
}; 

Chức năng trên khi gọi là

async_function(42, function(val) { 
    console.log(val) 
}); 
console.log(43); 

Sẽ in 42 ra cửa sổ Console không đồng bộ. Đặc biệt process.nextTick cháy sau khi cuộc gọi calllack hiện tại đang trống. Ngăn xếp cuộc gọi đó trống sau async_functionconsole.log(43) đã chạy. Vì vậy, chúng tôi in 43 theo sau là 42.

Bạn có lẽ nên thực hiện một số thao tác đọc trên vòng lặp sự kiện.

+0

Tôi đã nhìn thấy các vạt Dahl, nhưng tôi dường như không nắm bắt được vấn đề tôi sợ. :( – Kriem

+1

@Kiểm tra xem câu trả lời cập nhật và đọc [về vòng lặp sự kiện] (http://en.wikipedia.org/wiki/Event_loop) – Raynos

+1

Cảm ơn bạn đã hiểu rõ hơn về những gì tôi thiếu kiến ​​thức. :) Ví dụ cuối cùng của bạn đã giúp bạn. – Kriem

2

Hãy thử tính năng này, nó hoạt động cho cả nút và trình duyệt.

isNode = (typeof exports !== 'undefined') && 
(typeof module !== 'undefined') && 
(typeof module.exports !== 'undefined') && 
(typeof navigator === 'undefined' || typeof navigator.appName === 'undefined') ? true : false, 
asyncIt = (isNode ? function (func) { 
    process.nextTick(function() { 
    func(); 
    }); 
} : function (func) { 
    setTimeout(func, 5); 
}); 
+16

4 phiếu giảm giá và thậm chí không một bình luận mang tính xây dựng ..: \ – Omer

+6

@Omer Đây là cuộc sống trên SO. –

+0

Mã @Omer tự giải thích –

6

Chỉ cần chuyển qua cuộc gọi lại là không đủ. Bạn phải sử dụng bộ giải mã chẳng hạn, để làm cho chức năng không đồng bộ.

Ví dụ: chức năng Không async:

function a() { 
    var a = 0;  
    for(i=0; i<10000000; i++) { 
    a++; 
    }; 
    b(); 
}; 

function b() { 
    var a = 0;  
    for(i=0; i<10000000; i++) { 
    a++; 
    };  
    c(); 
}; 

function c() { 
    for(i=0; i<10000000; i++) { 
    }; 
    console.log("async finished!"); 
}; 

a(); 
console.log("This should be good"); 

Nếu bạn sẽ chạy trên Ví dụ, Điều này nên được tốt, sẽ phải chờ cho đến khi những chức năng sẽ hoàn thành công việc.

Pseudo multithread (async) chức năng:

function a() { 
    setTimeout (function() { 
    var a = 0; 
    for(i=0; i<10000000; i++) { 
     a++; 
    }; 
    b(); 
    }, 0); 
}; 

function b() { 
    setTimeout (function() { 
    var a = 0; 
    for(i=0; i<10000000; i++) { 
     a++; 
    }; 
    c(); 
    }, 0); 
}; 

function c() { 
    setTimeout (function() { 
    for(i=0; i<10000000; i++) { 
    }; 
    console.log("async finished!"); 
    }, 0); 
}; 

a(); 
console.log("This should be good"); 

một Đây sẽ là trully async. Điều này sẽ được tốt sẽ được viết trước khi async hoàn thành.

0

Nếu bạn BIẾT rằng một hàm trả về lời hứa, tôi khuyên bạn nên sử dụng các tính năng async/await mới trong JavaScript. Nó làm cho cú pháp trông đồng bộ nhưng hoạt động không đồng bộ. Khi bạn thêm từ khóa async đến một chức năng, nó cho phép bạn await lời hứa trong phạm vi đó:

async function ace() { 
    var r = await new Promise((resolve, reject) => { 
    resolve(true) 
    }); 

    console.log(r); // true 
} 

nếu một hàm không trả lại một lời hứa, tôi khuyên bạn nên gói nó trong một lời hứa mới mà bạn xác định, sau đó giải quyết dữ liệu bạn muốn:

function ajax_call(url, method) { 
    return new Promise((resolve, reject) => { 
    fetch(url, { method }) 
    .then(resp => resp.json()) 
    .then(json => { resolve(json); }) 
    }); 
} 

async function your_function() { 
    var json = await ajax_call('www.api-example.com/some_data', 'GET'); 
    console.log(json); // { status: 200, data: ... } 
} 

Tóm lại: tận dụng sức mạnh của lời hứa.

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