2016-02-10 6 views
0

Рассмотрим Node.js цикла, чтобы выпалить HTTP запросов, например:минимального node.js синхронное ожидания по запросу HTTP

var http = require('http'); 

function sendOne(opts, body) 
{ 
    var post_options = { 
... 
    } 

    var sender = http.request(post_options, function(res) { 
     // process response 
    }); 

    sender.write(body) 
    sender.end() 
    return sender; 
} 

for(var i =0; i < maxUploadIterations; i++) 
{ 
    var body = // construct payload 
    var sent = sendOne(opts, body); 
    // somehow wait on sent... 
} 

Обратите внимание, что http.request объект имеет функцию обратного вызова, указанную для обработки ответа , Мой вопрос: как я могу синхронно ждать объекта «Отправленный», возвращенного из sendOne , используя встроенные примитивы Node.

Я понимаю, что есть несколько фреймворков, таких как Express и Futures, которые могут справиться с этим, но я хочу понять примитивное поведение, а не использовать «магическую» структуру.

Можно ли принимать «Отправленные» и поставить обработчик на него, как это:

var sent = ... 
sent.on("complete", function() { ... }); 

?

Если да, то какой именно обработчик и как форматировать цикл?

+1

Одна вещь, которую вы могли бы сделать, это обернуть ее в [Promise] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). Я знаю, что вы сказали, что вам не нужна фреймворк, но Promises являются частью ES6 и теперь являются частью node.js. – zero298

+0

Я согласен с @ zero298, но вы также можете взглянуть на исходный код [sync-request] (https://github.com/ForbesLindesay/sync-request), упомянутый в [this] (http: // stackoverflow. com/a/32961480) вопрос. –

+0

Вы действительно хотите делать синхронные запросы или хотите знать, как ждать асинхронных операций? Это не одно и то же. – slebetman

ответ

1

Другой вариант, использовать обратные вызовы старой моды ... Хотя обещания могут быть более чистыми.

var http = require('http'); 

function sendOne(opts, body, next) { 
    var post_options = { 
     // ... 
    }; 

    var sender = http.request(post_options, function (res) { 
     // process response 
     next(); 
    }); 

    sender.write(body); 
    sender.end(); 
} 

var maxUploadIterations = 100; 
function next(index) { 
    // termination condition 
    if (index >= maxUploadIterations) { 
     return; 
    } 

    // setup next callback 
    var nextCallback = next.bind(null, index + 1); 

    // get these from wherever 
    var opts = {}; 
    var body = {}; 
    sendOne(opts, body, nextCallback); 
} 

next(0); 

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

+0

Я думаю, что это близко к моим требованиям. Похоже, я собираюсь завершить работу с стеком вызовов «next», который является maxUploadIterations глубоко. Узел очистит хвостовую рекурсию, или мне нужно знать об этом, когда maxUploadIterations становится действительно большим? – Brad

+0

Я не слишком разбираюсь в оптимизации высоких вызовов в ES6, думаю, вам нужно будет сгладить это до одной функции, чтобы обнаружить хвостовую рекурсию. Я не уверен, насколько это умный ... Это было бы не сложно, но я разделил функцию в основном на читаемость. –

+1

@Brad Я провел быстрый тест с использованием модуля отслеживания стека NPM (https://www.npmjs.com/package/stack-trace) с помощью NodeJS 5.5.0. Кажется, что он заблокирован на удобной глубине 3, поэтому либо NodeJS использует оптимизацию хвостовых вызовов, либо это артефакт планировщика работы. Я использовал 'setTimeout' вместо' http.request' для тестирования. Это может вести себя по-другому, хотя я подозреваю, что что-то, планирующее асинхронную работу, будет работать одинаково. Вам придется протестировать его для себя в своей среде. –

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