LearnYouNode - Jugglling Async (# 9) - я должен упускать что-то

Кажется, что существует много запросов var http = require ( 'http' ) var concat = require ( 'concat-stream' ) var args = process . argv . slice ( 2 , 5 ) var args_len = args . length var results = [] args . forEach ( function ( arg , i ) { http , получают ( Arg , функцию ( Рез ) { разреш . setEncoding ( 'utf8' ) Рез . трубу ( CONCAT ( функция ( ул ) { Результаты [ я ] = ул , если ( результаты . длина === args_len ) Результаты . Foreach ( функция ( val ) { console . log ( val ) }) })) }). на ( 'ошибка' , консоль . ошибки ) }) ONS о й вар HTTP = требуется ( 'HTTP' ) вар бл = требуется ( 'бл' ) вар результаты = [] вар COUNT = 0 функция printResults () { для ( вар я = 0 ; я < 3 ; я ++) консоли . log ( results [ i ]) } function httpGet ( index ) { http . get ( process . argv [ 2 + index ], function ( response ) { response . pipe ( bl ( function ( err , data ) { if ( err ) return console . error ( err ) results [ index ] = data . toString () count ++ if ( count == 3 ) printResults () })) }) } for ( var i = 0 ; i < 3 ; i ++) httpGet ( i ) проблема здесь, но ни один dlearnyounoderectly не относится к моим запросам .lengthon AFAICT. Вот описание проблемы:

Эта проблема аналогична предыдущей проблеме (HTTP COLLECT) в том, что вам нужно использовать http.get (). Однако на этот раз вам будут предоставлены три URL-адреса в качестве первых трех аргументов командной строки.

Вы должны собрать полный контент, предоставленный вам каждым URL-адресом, и распечатать его на консоли (stdout). Вам не нужно печатать длину, просто данные в виде строки; по одной строке на URL. Уловка заключается в том, что вы должны распечатать их в том же порядке, что и URL-адреса, предоставленные вам в качестве аргументов командной строки.

Вот мое первоначальное решение, которое терпит неудачу:

0

Это решение, которое они рекомендуют:

1

То, что я не понимаю, - это принципиальное различие между моим кодом и официальным решением. Я делаю то же самое, что и их решение, когда дело доходит до наполнения ответов в массив для ссылки позже. Они используют 2er для подсчета количества обратных вызовов, в то время как я сравниваю длину двух массивов (один из которых увеличивает каждый обратный вызов); это имеет значение? Когда я пытаюсь решить свое решение за пределами .lengthпрограммы, кажется, все работает нормально. Но я знаю, что это, вероятно, мало значит ... Так что кто-то знает узел лучше, чем я ... помогите объяснить, где я поступил неправильно? ТИА.

javascript,arrays,node.js,

вар результаты = [] консоль . log ( results . length ) // 0 - как ожидаемые результаты [ 1 ] = «lo» ; консоль . log ( результаты . длина ) // 2 - sic! результаты [ 0 ] = «Хел» ; консоль . log ( results . length ) // 2 - не изменился! результаты [ 3 ] = "ld!" ; консоль . log ( результаты . длина ) // 4 результата [ 2 ] = «Wor» ; консоль . log ( результаты . длина ) // 4

Ответов: count


«Привет, леди!» "Привет мир!" 032582" > вверх голосование 0 принял

Они используют счетчик для подсчета количества обратных вызовов, в то время как я сравниваю длину двух массивов (один из которых увеличивает каждый обратный вызов); это имеет значение?

Да, это имеет значение. .lengthМассива зависит от самого высокого индекса в массиве, а не фактическое количество выделенных элементов.

Разница возникает только тогда, когда результаты асинхронных запросов возвращаются из строя . Если вы сначала присвоите индекс 0, затем 1, затем 2и т. Д., iОно будет соответствовать числу назначенных элементов и будет таким же, как и их counter. Но теперь попробуйте:

i

Если вы проверите длину после каждого присваивания и выведете массив всякий раз, когда получите 4, он будет печатать

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

var args = process.argv.slice(2, 5)
var args_len = args.length
var results = []
var count = 0

function get_url_save(url, idx) {
    http.get(url, function(res) {
        res.setEncoding('utf8')
        res.pipe(concat(function(str) {
            results[idx] = str
            if (++count === args_len)
                results.forEach(function(val) {
                    console.log(val)
                })
        }))
    }).on('error', console.error)
}

args.forEach(function(arg, i) {
    get_url_save(arg, i)
})

0

Итак, оказывается, здесь были две разные проблемы, одна из которых была отмечена @Bergi выше. Эти две проблемы заключаются в следующем:

  • forEachМетод не возвращает количество элементов в массиве. Скорее он возвращает самый высокий индекс, который доступен. Это кажется довольно глупым. Спасибо @Bergi за это.
  • Область видимости iпеременной является неправильной, и как таковая значение iможет меняться. Это приводит к состоянию гонки, когда результаты возвращаются.

Мое окончательное решение оказалось следующим:

i

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

JavaScript, массивы, Node.js,
Похожие вопросы