@Pointy ответил на этот вопрос односложно уже, но позвольте мне объяснить, это немного более ясно: те вложенные функции не запускаются в том порядке, в котором вы думаете.
Node.js является неблокирующим и использует неявный цикл событий Javascript для их выполнения при их готовности.Вот ваш код с номерами строк:
/*01*/ client.on('test', function(req, fn) {
/*02*/ var returnArr = [];
/*03*/ redis.hkeys(req, function (err, replies) {
/*04*/ replies.forEach(function(reply, i) {
/*05*/ if (reply.indexOf('list.') > -1) {
/*06*/ redis.hgetall(reply.substring(5), function(err, r) {
/*07*/ returnArr.push({name:r['name'],index:i});
/*08*/ console.log(returnArr);
/*09*/ });
/*10*/ }
/*11*/ });
/*12*/ console.log(returnArr);
/*13*/ });
/*14*/ console.log(returnArr);
/*15*/ });
/*16*/ //Any other code you have after this.
Итак, каков порядок выполнения этой вещи?
Строка 1: зарегистрируйте обработчик событий для события 'test'.
Линия 16: Начало работы любой другой код, который будет работать во время этого прохода через цикл событий
Line 2: A «тест» событие было получено в какой-то момент по циклу событий и в настоящее время обрабатывается, поэтому инициализируется returnArr
Строка 3: Выполняется неблокирующий запрос ввода-вывода, и функция обратного вызова регистрируется для выполнения, когда соответствующее событие помещается в очередь в цикле событий.
Строка 14-15: Выполняется console.log
Выполняется эта функция, которая должна заканчивать текущее обрабатываемое событие.
Строка 4: Событие запроса возвращается и выполняется обратный вызов. Метод forEach
является одним из немногих , блокирующих методы Node.js с обратным вызовом, поэтому каждый обратный вызов выполняется для каждого ответа.
Строка 5: if
оператор выполняются и либо заканчивается (переходят в линии 10) или поступают в блоке (идет к строке 6)
Строка 6: Запрос неблокирующего ввода-вывода выполняются, при добавлении нового событие в цикл событий и новый обратный вызов, который будет запущен, когда событие вернется.
Строка 9: Завершение регистрации обратного вызова.
Линия 10: Завершает if
заявление
Строка 11: Завершает `forEach
обратных вызовов.
Линия 12: Выполнение второгоconsole.log
запрос , который до сих пор не имеет ничего в returnArr
Линия 7: Одна из возвращений событий и пожаров обработчик событий. Новым данным присваивается returnArr
.
Строка 8: перваяconsole.log
выполнено. В зависимости от того, какое событие это, длина массива будет отличаться. Также порядок элементов массива НЕ должен соответствовать порядку ответов, перечисленных в массиве replies
.
По существу, вы можете посмотреть на более глубоко вложенные функциях, выполнение после полноты менее, глубоко вложенных функций (потому что это то, что происходит, по сути), независимо от того, содержит ли метод заявление после вложенной неблокируемой обратный вызов или нет.
Если это смущает вас, вы можете написать код обратного вызова в Continuation Passing Style так что очевидно, что все во внешней функции выполняются до внутренней функции, или вы можете использовать this nice async library, чтобы сделать ваш код выглядеть более важен.
Это, я думаю, отвечает на ваш реальный вопрос, а не на тот, который вы ввели.
Не вызывайте переменную 'return'. –
Я изменил исходный вопрос, когда вы отправляете вопрос, я изменил имя переменной, не задумываясь. Это происходит независимо от его имени. – grsx