Для цикла с Node JS обещание цепочки

Как и все остальные, я провел дни, пытаясь понять это. Я был в этой теме, пробуя каждую комбинацию того, что вы все сказали, и ничего. Я, наконец, пошел в AppData / Local / Microsoft / VisualStudio и удалил все папки там. Затем приступил к отключению всего в моем Антивирусе, и я, наконец, получил базовую установку, чтобы пройти весь путь. Разочарование, но, надеюсь, это поможет кому-то, кто все пробовал.

0
задан user7623678 27 March 2019 в 09:24
поделиться

1 ответ

У вас есть проблема с областью действия.

Это пример для воспроизведения вашей проблемы:

ques - глобальная переменная, которая обновляется в цикле for, поэтому при асинхронности Код завершается, выполнение будет считывать глобальную переменную с последним значением ques = result[i].

'use strict'
const result = ['a', 'b', 'c']
const mcqAll = []
var ques
for (var i = 0; i < result.length; i++) {
  ques = result[i]
  var sql_test_q_ops = 'SELECT op_text, op_id FROM mc_ops WHERE q_id = ' + result[i].q_id
  query(sql_test_q_ops)
    .then(() => {
      mcqAll.push({ i: ques })
      console.log(mcqAll)
    })
}

function query() {
  return new Promise(resolve => setTimeout(resolve, 100))
}

Но, если вы просто объявите ques следующим образом:

for (var i = 0; i < result.length; i++) {
  const ques = result[i]
  const sql_test_q_op...

все будет работать.

Хорошей практикой является использование const или let вместо var, поскольку последний создает опасную глобальную переменную области действия.


Что касается вашего комментария: вывод пустой, потому что этот цикл for является синхронизированным, поэтому вы отвечаете синхронизированным способом на ответ.

Пример того, как управлять этим делом, может быть таким:

'use strict'
const result = ['a', 'b', 'c']
const mcqAll = []

const promiseArray = result.map(ques => {
  const sql_test_q_ops = 'SELECT op_text, op_id FROM mc_ops WHERE q_id = ' + ques.q_id
  return query(sql_test_q_ops)
    .then(() => { mcqAll.push({ i: ques }) })
})

// Wait for all the query to complete before rendering the results
Promise.all(promiseArray)
  .then(() => {
    console.log({ mcqAll });
    res.render('mcqAllPage', { mcqAll })
  })
  .catch(err => res.send(500)) // this is an example

function query() {
  return new Promise(resolve => setTimeout(resolve, 100))
}

Учтите, что существует множество возможностей для реализации этого:

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

Идите глубже и выберите тот, который лучше всего соответствует вашим потребностям.

Важно: .catch всегда цепочка обещаний!

0
ответ дан Manuel Spigolon 27 March 2019 в 09:24
поделиться
Другие вопросы по тегам:

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