Изображения BLOB-объектов не помещаются в массив в правильном порядке - PullRequest
1 голос
/ 27 мая 2020

У меня есть функция toBlobConverter, которая отправляется на l oop, чтобы разрезать изображение на 9 частей, но изображения не расположены в правильном порядке. Рад вас слышать.

const toBlobConverter = async (x, y) => {
  var canvas = document.createElement("canvas");
  canvas.width = widthOfOnePiece;
  canvas.height = heightOfOnePiece;
  var context = canvas.getContext("2d");
  context.drawImage(
    image,
    y * widthOfOnePiece,
    x * heightOfOnePiece,
    widthOfOnePiece,
    heightOfOnePiece,
    0,
    0,
    canvas.width,
    canvas.height
  );
  async function operation() {
    return new Promise(function (resolve, reject) {
      canvas.toBlob(resolve);
    });
  }
  const compOperation = await operation();
  console.log(compOperation);
  return imagePieces.push({
    url: URL.createObjectURL(compOperation),
    blob: compOperation,
  });
}
for (var x = 0; x < 3; ++x) {
  for (var y = 0; y < 3; ++y) {
    toBlobConverter(x, y)
  }
}

1 Ответ

1 голос
/ 27 мая 2020

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

Если вы хотите, чтобы они выполняли свою работу параллельно, вы можете использовать Promise.all, чтобы получить результаты в том порядке, в котором вы их просили. Это потребует реорганизации вашего кода немного , но, возможно, в лучшую сторону, поскольку не требуется toBlobConverter для «магического» заполнения imagePieces; см. комментарии ***:

const toBlobConverter = async (x, y) => {
  var canvas = document.createElement("canvas");
  canvas.width = widthOfOnePiece;
  canvas.height = heightOfOnePiece;
  var context = canvas.getContext("2d");
  context.drawImage(
    image,
    y * widthOfOnePiece,
    x * heightOfOnePiece,
    widthOfOnePiece,
    heightOfOnePiece,
    0,
    0,
    canvas.width,
    canvas.height
  );
  async function operation() {
    return new Promise(function (resolve, reject) {
      canvas.toBlob(resolve);
    });
  }
  const compOperation = await operation();
  console.log(compOperation);
  // *** Return the entry rather than pushing it
  return {
    url: URL.createObjectURL(compOperation),
    blob: compOperation,
  };
}

// *** Build an array of the promises in the  order you want
const promises = [];
for (var x = 0; x < 3; ++x) {
  for (var y = 0; y < 3; ++y) {
    promises.push(toBlobConverter(x, y));
  }
}

// *** Wait for the operations to complete
Promise.all(promises)
.then(results => {
    // *** `results` is in the same order `promises` was
    imagePieces.push(...results);
})
.catch(error => {
    // Handle/report errors
});

Если вы хотите, чтобы они выполнялись один за другим (в серии ), просто поместите свои for циклы в функцию async и await результат toBlobConverter:

(async () => {
    for (var x = 0; x < 3; ++x) {
      for (var y = 0; y < 3; ++y) {
        await toBlobConverter(x, y)
      }
    }
})()
.catch(error => {
    // Handle errors...
});

Как бы то ни было, при написании современного кода я настоятельно рекомендую не использовать var. Везде. :-) Используйте let или const.

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