Как заставить цикл for перебирать дополнительный элемент, добавленный в массив из результата db? - PullRequest
0 голосов
/ 29 января 2019

У меня есть массив.Я хочу сделать запрос к базе данных MySQL с каждым элементом массива и при выполнении определенного условия, я хочу добавить дополнительные элементы в тот же массив и перебрать и эти элементы.

Я новичок в nodejs, поэтому яНе знаю, правильный ли это подход.

Я предоставил фрагмент кода, который является упрощенной версией моей проблемы.

В приведенном ниже фрагменте кода я хочу отобразить "выглядит хорошо"на консоли.

pre_req_subjects_arr = [2310,2320,2410];
for(let j=0;j<pre_req_subjects_arr.length;j++) {
    console.log("j is : "+j);
    db.query("SELECT `NUMBER` FROM `COURSE`",function(err,preOfPreReq) {
        if(err) {
            console.log("Error while creating array of pre_req subjects : " + err);
        } else {
            console.log("j inside db query : "+j);
            if(j==1) {
                pre_req_subjects_arr.push(1111);    
            }
            if(pre_req_subjects_arr[j] == 1111) {
                console.log("looks good");
            }
        }
    })                                        
}

setTimeout(function() {
    console.log("pre_req_subjects_arr is " + JSON.stringify(pre_req_subjects_arr));
}, 1000);

Вывод:

j is : 0
j is : 1
j is : 2


j inside db query : 0
j inside db query : 1
j inside db query : 2



pre_req_subject_arr : [2310,2320,2410,1111]

Ожидаемый вывод:

j is : 0
j is : 1
j is : 2
j is : 3

j inside db query : 0
j inside db query : 1
j inside db query : 2
j inside db query : 3 

looks good  
pre_req_subject_arr : [2310,2320,2410,1111]

Ответы [ 4 ]

0 голосов
/ 29 января 2019

Проблема в том, что цикл for не ожидает завершения обратного вызова для каждой итерации.Поскольку ваша база данных не поддерживает обещания, вы можете заключить запрос в обещание,

(async () => {
  let pre_req_subjects_arr = [2310, 2320, 2410];
  for (const [j, value] of pre_req_subjects_arr.entries()) {
    console.log("j is : " + j);
    const preOfPreReq = await executeQuery("SELECT `NUMBER` FROM `COURSE`");
    console.log("j inside db query : " + j);
    if (j == 1) {
      pre_req_subjects_arr.push(1111);
    }
    if (pre_req_subjects_arr[j] == 1111) {
      console.log("looks good");
    }
  }
  console.log(
    "pre_req_subjects_arr is " + JSON.stringify(pre_req_subjects_arr)
  );
})();

const executeQuery = queryStr => {
  return new Promise(function(resolve, reject) {
    db.query(queryStr, function(err, results) {
      if (err) {
        return reject(err);
      }
      return resolve(results);
    });
  });
};
0 голосов
/ 29 января 2019

Поскольку API вашей базы данных является асинхронным, ваш цикл for будет завершен до выполнения любого из db.query обратных вызовов.Поэтому, когда вы push там, уже слишком поздно для цикла for - он уже завершен.

Вы должны посмотреть на обещания, и, возможно, ваша база данных API поддерживает обещания.В этом случае используйте эту возможность.Но из комментариев я понимаю, что вы используете пакет mysql , который не имеет поддержки обещаний.

Принцип (с обещаниями или без них) заключается в том, что вы ждете завершения каждого запроса, прежде чем продолжить выполнениеСледующая «итерация».Вам понадобится какой-то асинхронный цикл для достижения этого.Например, вы можете использовать эту функцию:

var pre_req_subjects_arr = [2310,2320,2410];

(function loop(j) {
    if (j >= pre_req_subjects_arr.length) {  // all "iterations" done!
        console.log("pre_req_subjects_arr is " + JSON.stringify(pre_req_subjects_arr));
        return;
    }
    console.log("j is : "+j);

    db.query("SELECT `NUMBER` FROM `COURSE`",function(err,preOfPreReq) {
        if(err) {
            console.log("Error while creating array of pre_req subjects : " + err);
        } else {
            console.log("j inside db query : "+j);
            if(j==1) {
                pre_req_subjects_arr.push(1111);
            }
            if(pre_req_subjects_arr[j] == 1111) {
                console.log("looks good");
            }
        }
        loop(j+1); // Only now call the next "iteration"
    })                 
})(0); // start the first iteration

В качестве альтернативы вы можете обещать метод query и затем использовать силу await:

// Create a promisified version of db.query
const queryPromise = (db, sql) => 
    new Promise((resolve, reject) => 
        db.query(sql, (err, result) => err ? reject(err) : resolve(result))
    );

// Now you can use async/await and a for-loop
(async function () {
    const pre_req_subjects_arr = [2310,2320,2410];

    for (let j = 0; j < pre_req_subjects_arr.length; j++) {
        console.log("j is : "+j);
        try {
            const preOfPreReq = await queryPromise(db, "SELECT `NUMBER` FROM `COURSE`");
            console.log("j inside db query : "+j);
            if (j==1) {
                pre_req_subjects_arr.push(1111);
            }
            if (pre_req_subjects_arr[j] == 1111) {
                console.log("looks good");
            }
        } catch(e) {
            console.log("Error while creating array of pre_req subjects : " + e);
        }
    }
    console.log("pre_req_subjects_arr is " + JSON.stringify(pre_req_subjects_arr));
})();

NB: Как примечание: вообще плохая идея выполнять SQL-запрос в цикле.Обычно вы можете заменить это одним более умным запросом.

0 голосов
/ 29 января 2019
const preReqSubjectsArr = [2310, 2320, 2410];

let condition = true;

for (let j = 0; j < preReqSubjectsArr.length; j++) {
  console.log('j is : ' + j);

  db.query('SELECT `NUMBER` FROM `COURSE`', function(err, preOfPreReq) {
    if (err) {
      console.log('Error while creating array of pre_req subjects : ' + err);
    } else {
      if (condition === true && j === 1) {
        condition = false;

        preReqSubjectsArr.splice(j, 0, 1111);

        j--;
      } else {
        console.log('j inside db query : ' + preReqSubjectsArr[j]);
      }

      if (preReqSubjectsArr[j] === 1111) {
        console.log('looks good');
      }
    }
  });
}

setTimeout(function() {
  console.log('preReqSubjectsArr ', JSON.stringify(preReqSubjectsArr));
}, 1000);

вывод:

j is : 0
j inside db query : 2310
j is : 1
j is : 1
j inside db query : 1111
looks good
j is : 2
j inside db query : 2320
j is : 3
j inside db query : 2410
preReqSubjectsArr  [2310,1111,2320,2410]

Надеюсь, я правильно понял задачу!

0 голосов
/ 29 января 2019

setTimeout никогда не является хорошим способом сделать это.

если вам это нужно, вы должны пересмотреть логику вашего кода

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