2013-09-10 3 views
1

Этот вопрос задан по-разному уже здесь, и я хорошо понимаю проблему. Общее решение - вызывать обратные вызовы для обработки HTTP-результатов, но я специально хочу этого избежать.Ожидание асинхронного HTTP-запроса для завершения

Я предположил, что могу использовать флаг «мы сделали еще», чтобы все работало, но это не работает должным образом.

// 
// Test the IP the comment came-from. 
// 
exports.testJSON = function (obj) 
{ 
    var ip  = obj['ip'] || ""; 
    var result = null; 
    var done = false; 

    // 
    // The URL request we're going to make 
    // 
    var options = { 
     host: 'www.stopforumspam.com', 
     port: 80, 
     path: '/api?ip=' + ip 
    }; 

    // 
    // A GET request 
    // 
    var re = http.request(options, function(res) { 
     var str = ''; 

     res.on('data', function(chunk) { 
      console.log("Got data " + chunk); 
      str += chunk; 
     }); 
     res.on('end', function() { 
      console.log("Got END"); 
      result = "..... "; 
      done = true; 
     }); 
     }).on('error', function(e) { 
     done = true; 
     console.log("Got error: ", e); 
    }); 

    re.end(); 

    while(! done) { 
    } 

    return(result); 
}; 

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

Добавление в "process.nextTick()" в "while (! Done) {}" петли тоже не имеет значения.

Несомненно, мне не нужно перерабатывать всю систему плагинов, чтобы справиться с другим подходом, а обратный вызов обновления «сделанного» флага будет работать, как-то?

+0

Является ли ваша система плагина написанной на JavaScript? –

+0

Прошу прощения, но если вы пытаетесь использовать синхронный цикл для проверки асинхронного результата, вы не очень хорошо понимаете проблему. Кажется, что вы пытаетесь сделать, _return_ результат от асинхронного вызова, невозможно в javascript (afaik). Любой синхронный код будет либо блокировать весь поток (предотвращая выполнение запроса), либо возвращаться до того, как будет выполнен запрос. –

+0

Я полагаю, что можно заставить его работать, взломав некоторые [process.binding] (http://stackoverflow.com/questions/17336779/if-nodejs-uses-non-blocking-io-how-is-fs-readfilesync-implemented), но я бы не рекомендовал его. –

ответ

2

Если ваша вся система плагинов использует JavaScript, переработка, вероятно, не будет плохой идеей. Если вы не хотите иметь дело с асинхронным кодом с помощью обратных вызовов, вы можете рассмотреть обещания как другое решение для управления асинхронным кодом. Библиотека "q" может быть хорошим местом для начала.

Альтернативой может быть использование node-fibers. Я никогда не использовал его раньше, но примеры просты. Возьмите нормальную структуру обратного вызова, например:

console.log('waiting 2 seconds...'); 
setTimeout(function() { 
    console.log('Finished!'); 
}, 2000); 

Аналогичный пример использования узла-волокна:

var Fiber = require('fibers'); 

function wait(ms) { 
    var fiber = Fiber.current; 
    setTimeout(function() { 
     fiber.run(); 
    }, ms); 
    Fiber.yield(); 
} 

Fiber(function() { 
    console.log('waiting 3 seconds...'); 
    wait(1000); 
    console.log('waiting 2 seconds...'); 
    wait(1000); 
    console.log('waiting 1 seconds...'); 
    wait(1000); 
    console.log('done!'); 
}).run(); 

Существует небольшая упаковка, чтобы сделать, чтобы получить узел-волокна функционировать, но теперь вы можете избегать обращения к обратным вызовам и синхронным использованием асинхронного кода.

+2

Стоит упомянуть, почему его решение не работает - его node.js код работает в одном потоке, а цикл while удерживает управление потоком навсегда, поэтому обратный вызов никогда не может быть вызван. –

+1

Действительно. Похоже, я должен посмотреть некоторые из модулей обещания/очереди mpm и посмотреть если я смогу найти хорошую подгонку. –

+0

Я использовал библиотеку [async] (https://github.com/caolan/async) в прошлом - возможно, стоит взглянуть на нее. –

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