Рисование холста: ожидание загрузки изображений рекурсивным методом - PullRequest
0 голосов
/ 24 апреля 2019

Я реализую рекурсивный метод, который берет массив изображений и рисует их в холст:

async drawImages(ctx, images): Promise<any> {
    const img = images.shift();
    const imgToDraw = new Image();
    imgToDraw.src = img.src;
    imgToDraw.onload = () => {
        ctx.drawImage(imgToDraw, img.x, img.y, img.w, img.h);
        if (images.length > 0) {
            this.drawImages(ctx, images);
        } else {
            console.log("I - Processing");
            return Promise.resolve();
        }
    }
}

В конце выполнения этого метода мне нужно получить DataURL холстаи я делаю это так:

someCallingMethod() {
    //...
    await this.drawImages(ctx, images);
    console.log("II - Finished");
    console.log(canvas.toDataURL());
}

Проблема, с которой я сталкиваюсь, заключается в том, что ожидание не работает по методу drawImages.При выполнении этого кода я всегда получаю лог "II - Finished" перед "I - Processing", и поэтому canvas.toDataURL() никогда не содержит изображений, которые должны быть нарисованы на холсте.

Спасибо

1 Ответ

1 голос
/ 24 апреля 2019

Вам необходимо вернуть Обещание синхронно.
Здесь вы возвращаете его в асинхронном onload обработчике событий.
Так что drawImages не вернет Обещание, но не определено.

Кроме того, вы захотите возвращать следующую итерацию drawImages каждый раз, чтобы ваш внешний await ждал всех этих Обещаний:

const obj = {
  async drawImages(ctx, images) {
    // return a Promise synchronously
    return new Promise((resolve, reject) => {
      const img = images.shift();
      const imgToDraw = new Image();
      imgToDraw.src = img.src;
      imgToDraw.onload = () => {
        ctx.drawImage(imgToDraw, img.x, img.y, img.w, img.h);
        if (images.length > 0) {
          // resolve with next iteration so we can await all
          resolve(this.drawImages(ctx, images));
        } else {
          console.log("I - Processing");
          // done
          resolve();
        }
      };
      imgToDraw.onerror = reject;
    });
  }
};

(async () => {
  const images = [];
  // picsum.photos doesn't fill all the indexes...
  const urls = ["01", "02", "03", "04", "05", "06", "10", "11", "12", "13"];
  const s = 50; // image size
  for(let i=0; i<10; i++) {
    images.push( {
      src: `https://picsum.photos/${s}/${s}?image=10` + urls[i],
      x: (i%5)*s,
      y: Math.floor(i/5)*s,
      w: s,
      h: s
    });
  }
  const ctx = canvas.getContext('2d');
  await obj.drawImages(ctx, images);
  // fill a green rect over to show we are able to await it
  ctx.fillStyle = 'rgba(0,255,0, 0.2)';
  ctx.fillRect(0,0,canvas.width,canvas.height);
  console.log("all done");
})();
<canvas id="canvas" width="250" height="100"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...