Veneomin
@Veneomin

Почему не видно значения переменной?

Есть такой код:
for (var i=0; i<vendors.length; i++) {
    console.log(i)
    connection.query('SELECT * FROM `brends` WHERE `brend_parrent`="'+vendors[і].id_folders+'";', function(err, rows, fields) {
        if (err) throw err;
        console.log(i)
   })
}

Первый консоль лог выводит i правильно, 2й выводит всегда максимальное значение. Почему так? И да, возможно есть способ получше чем делать выборку из БД циклом?
  • Вопрос задан
  • 263 просмотра
Решения вопроса 1
@schurin
Люблю катать с гор, особенно на санках
Все колбэки которые ты передаёшь в метод query встают в очередь на выполнение, за это время цикл успевает отработать до конца и когда берем значение итератора в колбэке, получаем значение по ссылке, в которой уже нарастили итератор до максимального, выход:
1. Передавать итератор в колбэк для каждого запроса --> (err, rows, fields, i)
2. Использовать forEach
[0,1,2,3].forEach(function(item, index){
	setTimeout(function(){
		console.log(index)
	}, 0)
})
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
HoHsi
@HoHsi
Это называется IIFE. Так как запрос к базе - асинхонный, а for - синхонный, он отрабатывает быстрее, сохраняя внутренее значение i на финальной итерации. Это значит, что вам нужно замкнуть для каждого вызова i, что-бы он стал локальным. Это проблема var переменны, так как имеют область видимости всей функции, а не блока. Это можно решить:
1 вариант - по старинке:
for (var i=0, len = vendors.length; i < len ; i++) {
    (function (i) {
        console.log(i);
        connection.query('SELECT * FROM `brends` WHERE `brend_parrent`="'+vendors[і].id_folders+'";', function(err, rows, fields) {
            if (err) throw err;
            console.log(i);
        });
    })(i);
}


2 - с использованием ES6 let:
for (let i=0, len = vendors.length; i < len ; i++) {
    console.log(i);
    connection.query('SELECT * FROM `brends` WHERE `brend_parrent`="'+vendors[і].id_folders+'";', function(err, rows, fields) {
        if (err) throw err;
        console.log(i);
   });
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы