Асинхронный файл конвейера для HTTP-запроса

Я пытаюсь отправить чередующиеся запросы GET и POST на сервер, но запрос POST отправляет данные из файла, что, похоже, сбивает время.

var async = require('async');
var http = require('http');
var request = require('request');
var fs = require('fs');

var arr = [];
for (var i = 1; i <= 50; i++) {
   arr.push(i);
}

var limitedAgent = new http.Agent({maxSockets: 6});

function processThenSendRequest(data, onfinish) {
    request.get({
        url: 'http://www.google.com',
        pool: limitedAgent
    }, (function(j) {
        return function(err, res) {
            console.log("GET: response from " + j);
        };
    })(data)).on('socket', (function(j) {
        return function(socket) {
            console.log("GET: socket assigned for " + j);
        }
    })(data));

    var source = fs.createReadStream('README.md');

    var postReq = request.post({
        url: 'http://www.google.com',
        pool: limitedAgent
    }, (function(j) {
        return function(err, res) {
            console.log("POST: response from " + j);
        };
    })(data)).on('socket', (function(j) {
        return function(socket) {
            console.log("POST: socket assigned for " + j);
        }
        })(data));

    // source.pipe(postReq);

    setTimeout(function() {
        onfinish(null, data);
    }, 10000);
}

async.map(arr, processThenSendRequest, function(err, results) {
    if (err) console.error(err);
    console.log("finished");
});

Код, как написано выше, работает нормально, запросы GET и POST отправляются в чередующемся порядке, но если я раскомментирую строку source.pipe(postReq), то все запросы GET отправляются перед всеми запросами POST.

Есть ли решение этой проблемы? Я мог бы использовать async.mapLimit, но это похоже на взлом и что решение должно быть через библиотеку запросов - хотя это впечатление может быть основано на недоразумении.


person knightian    schedule 24.07.2015    source источник
comment
Поскольку Node полностью не блокирует (по крайней мере, когда он написан таким образом), вы не можете быть уверены, что что-то произойдет по порядку, если вы не запустите его последовательно. async.series также может сделать это за вас, или async.eachSeries.   -  person brandonscript    schedule 24.07.2015
comment
Это не связано, но дополнительные замыкания в processThenSendRequest, которые связывают data, не нужны, потому что data уже привязан к processThenSendRequest и значение не изменится для этого вызова.   -  person mscdex    schedule 24.07.2015
comment
@mscdex Спасибо, что указали на это - это имеет смысл и полезно для меня.   -  person knightian    schedule 24.07.2015
comment
@remus Понятно - это имеет смысл. В этом случае я буду использовать async.mapLimit для того, что я делаю, так как мне не нужно, чтобы это было идеально последовательно, но ваш комментарий помогает прояснить, что происходит для меня.   -  person knightian    schedule 24.07.2015


Ответы (1)


По моему комментарию:

Поскольку Node полностью не блокирует (по крайней мере, когда он написан таким образом), вы не можете быть уверены, что что-то произойдет по порядку, если вы не запустите его последовательно. async.series также может сделать это за вас, или async.eachSeries.

Кроме того, поскольку Node не ждет завершения асинхронных действий, каждая задача немедленно ставится в очередь, а обратные вызовы (событие завершения события) будут выполняться в порядке очереди. В вашем случае, поскольку запросы GET занимают гораздо меньше времени, чем запросы POST, поэтому они выполняются первыми.

person brandonscript    schedule 24.07.2015