как исправить неупорядоченную "выборку" в JavaScript - PullRequest
0 голосов
/ 06 ноября 2018

Я получаю несколько маршрутов, используя цикл for и сохраняю результат это мой код

 for (let i = 0; i < datesToFetch.length; i++) {


fetch("http://localhost:3000/areaChart/"+datesToFetch[i]+"/"+datesToFetch[i+1])
.then(response => response.json())
.then(response => console.log(response))

}

Что действительно странно, что порядок данных, которые я получаю, поступает в случайном порядке, а не в соответствии с порядком возрастания цикла, что действительно важно в этом случае

что мне делать, чтобы я получал данные в правильном порядке?

Ответы [ 4 ]

0 голосов
/ 06 ноября 2018

Это потому, что этот вызов извлечения будет добавлен в цикл событий JavaScript. Будет показан первый результат, который возвращает результат, поэтому порядок может отличаться от порядка их вызова.

Чтобы это исправить, вы должны взглянуть на оператора ожидания. Более подробную информацию можно найти здесь: https://dev.to/johnpaulada/synchronous-fetch-with-asyncawait

0 голосов
/ 06 ноября 2018

Ваш случай:

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

function getRandomInt(max) {
  return Math.floor(Math.random() * Math.floor(max));
}

function display(i) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(i);
    }, getRandomInt(1500));
  });
}

for (let i = 0; i < 5; i += 1) {
  display(i)
    .then(x => console.log('->', x));
}

Одно решение:

Мы используем функцию под названием Promise.all, чтобы подождать, пока все люди получат еду, а затем выйти из магазина.

function getRandomInt(max) {
  return Math.floor(Math.random() * Math.floor(max));
}

function display(i) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(i);
    }, getRandomInt(1500));
  });
}

const promises = [];

for (let i = 0; i < 5; i += 1) {
  promises.push(display(i));
}

// We use Promise.all to wait for all responses
// The responses are in the call order
Promise.all(promises)
  .then((rets) => {
      rets.forEach(x => console.log('->', x));
  });
0 голосов
/ 06 ноября 2018

Что происходит и как это исправить:

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

Если вместо этого вы хотите, чтобы цикл каждый раз останавливался и ждал, оберните его в функцию async и await извлечение.

async function test() {

    for (let i = 0; i < datesToFetch.length; i++) {
        var response = await fetch("http://localhost:3000/areaChart/"+datesToFetch[i]+"/"+datesToFetch[i+1]);
        var responseJson = await response.json();
        console.log(responseJson);
    }

}

Симуляция вашего кода:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

async function test() {
  for (let i = 1; i <= 5; i++) {
    console.log(`Starting call #${i}`);
    delay(5000 - (i * 1000))
      .then(() => console.log(`Call #${i} has completed.`));
  }
}

test();

Моделирование решения, представленного выше:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

async function test() {
  for (let i = 1; i <= 5; i++) {
    console.log(`Starting call #${i}`);
    await delay(5000 - (i * 1000));
    console.log(`Call #${i} has completed.`);
  }
}

test();
0 голосов
/ 06 ноября 2018

Добро пожаловать в асинхронный код!

Одна вещь, которую вы можете сделать, это создать пустой массив длиной datesToFetch.length и присвоить значение response.json() соответствующему индексу.

const responses = [...Array(datesToFetch.length)]

for (let i = 0; i < datesToFetch.length; i++) {
  fetch("http://localhost:3000/areaChart/"+datesToFetch[i]+"/"+datesToFetch[i])
    .then(response => response.json())
    .then(response => responses[i] = response)
}
...