Bạn nên gói lời gọi hàm đệ quy của mình thành một
setTimeout
,
setImmediate
hoặc là
process.nextTick
chức năng cung cấp cho node.js cơ hội để xóa ngăn xếp. Nếu bạn không làm điều đó và có nhiều vòng lặp mà không có bất kỳ lệnh gọi hàm không đồng bộ thực sự nào hoặc nếu bạn không đợi lệnh gọi lại, bạn RangeError: Maximum call stack size exceeded
sẽ không thể tránh khỏi .
Có rất nhiều bài báo liên quan đến "Vòng lặp không đồng bộ tiềm năng". Đây là một .
Bây giờ một số mã ví dụ khác:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
potAsyncLoop( i+1, resume );
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});
Đúng rồi đó:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
setTimeout( function() {
potAsyncLoop( i+1, resume );
}, 0 );
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});
Bây giờ, vòng lặp của bạn có thể trở nên quá chậm, vì chúng tôi mất một ít thời gian (một vòng trình duyệt) mỗi vòng. Nhưng bạn không cần phải gọi setTimeout
trong mỗi vòng. Thông thường, nó là ok để làm điều đó mỗi lần thứ 1000. Nhưng điều này có thể khác nhau tùy thuộc vào kích thước ngăn xếp của bạn:
var condition = false,
max = 1000000;
function potAsyncLoop( i, resume ) {
if( i < max ) {
if( condition ) {
someAsyncFunc( function( err, result ) {
potAsyncLoop( i+1, callback );
});
} else {
if( i % 1000 === 0 ) {
setTimeout( function() {
potAsyncLoop( i+1, resume );
}, 0 );
} else {
potAsyncLoop( i+1, resume );
}
}
} else {
resume();
}
}
potAsyncLoop( 0, function() {
...
});