2015-05-28 2 views
1

Я стараюсь следовать упражнениям из [узловой школы] [1]. Существует упражнение, в котором нужно собрать три потока и только распечатать вывод, когда все три потока выполнены. Без использования стороннего модуля.nodejs цикл событий, как правильно использовать nextTick

Может кто-нибудь указать, почему мой подход не работает? Она застревает в бесконечном цикле:

var http = require('http'); 
var concat = require('concat-stream'); 

var count = 3; 
var str1, str2, str3; 

http.get(process.argv[2], function (response) { 
    response.pipe(concat(function(data) {  
    str1 = data.toString(); 
    --count; 
    })); 
}); 

http.get(process.argv[3], function (response) { 
    response.pipe(concat(function(data) {  
    str2 = data.toString(); 
    --count; 
    })); 
}); 

http.get(process.argv[4], function (response) { 
    response.pipe(concat(function(data) {  
    str3 = data.toString(); 
    --count; 
    })); 
}); 

function foo() { 
    if (count > 0) {  
    process.nextTick(foo);  
    } else { 
    console.log(str1); 
    console.log(str2); 
    console.log(str3); 
    } 
}; 

foo(); 
+0

Вам не нужна рекурсивная функция. В случае успеха каждого запроса на получение, уменьшите счетчик, а затем проверьте, равно ли оно 0. Если оно равно 0, напечатайте строки. Ваш код выглядит так, как будто это сработает, но я бы использовал setTimeout вместо process.nextTick, так что рекурсии будут медленнее и менее интенсивны. проверка каждые 10-100 мс должна быть более чем достаточно быстрой. –

+0

Использование простой [асинхронной библиотеки] (https://github.com/caolan/async) позволит решить эту проблему менее чем за минуту. – tadman

+0

@tadman - возможно, вы пропустили часть о * Без использования стороннего модуля *. @kmansoor - вы используете 'concat-stream' ... который является сторонним модулем .... просто sayin ' –

ответ

0

http.get() обратные вызовы не могут работать до следующего такте цикла событий или более поздней версии. process.nextTick() ставит что-то прямо в начале цикла событий, перед обратными вызовами, которые уже есть.

Ваша рекурсивная рутина никогда не перестает рекурсировать, потому что она ждет, когда эти обратные вызовы уменьшат счетчик, но они никогда не срабатывают.

Это может сработать, если вы замените process.nextTick() на setImmediate(). (Я не проверял это, и если вы это сделаете, эй, дайте мне знать, работает ли это или нет.)

Но я бы сказал, просто избавиться от рекурсии. Это не нужно. Вы можете (например) сделать что-то вроде этого:

var count = 0; 

var httpGet = function (index) { 
    http.get(process.argv[2 + index], function (response) { 

     // Do stuff here 

     // This next bit will probably end up inside the callback provided to concat 
     count++; 
     if (count === 3) { 
     // Print results here 
     } 
    }) 
}; 

for (var i = 0; i < 3; i++) { 
    httpGet(i); 
} 
+0

Что произойдет, если 'httpGet (2)' завершается до 'httpGet (0)'? –

+0

Если 'httpGet (2)' завершается первым, то 'count === 3' оценивается как false до завершения' httpGet (0) ', после чего результаты печатаются. – Trott

+0

Вау, я совершенно неправильно читаю код! Извинения :) –

Смежные вопросы