Javascript - 等待数组完成填充

Hac*_*ode 3 javascript arrays asynchronous

我正在尝试获取某些数组元素的值。它适用于元素 [0]、[1]、[2]、[3],但不适用于 [4]。

function getBase64() {
  const urls = ['https://i.imgur.com/egNg7JU.jpg',
    'https://i.imgur.com/RLZ7WH1.jpg', 'https://i.imgur.com/qfabBbA.jpg',
    'https://i.imgur.com/Zuh1KaX.jpg', 'https://i.imgur.com/yD7X6Q1.jpg'
  ];

  let base64urls = [];

  const start = async () => {
    await asyncForEach(urls, async (num) => {
      await waitFor(50)
      toDataURL(num, function(dataURL) {
        base64urls.push(dataURL);
      });
    })
    console.log(base64urls);
    console.log(base64urls[4]);
  }
  start()

}

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array)
  }
}

const waitFor = (ms) => new Promise(r => setTimeout(r, ms))
Run Code Online (Sandbox Code Playgroud)

toDataURL简单地返回图像的 base64 值。每当我尝试console.log(base64urls[4]),它都会返回“未定义”。我确实得到了前面元素的正确值。有什么方法可以重构它,或者使用不同的方法来等待数组完全填充,然后再检查其元素的值?

编辑

这是我的 toDataURL

function toDataURL(src, callback) {
  const image = new Image();
  image.crossOrigin = 'Anonymous';

  image.onload = function () {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    canvas.height = this.naturalHeight;
    canvas.width = this.naturalWidth;
    context.drawImage(this, 0, 0);
    const dataURL = canvas.toDataURL('image/jpeg');
    callback(dataURL);
  };

  image.src = src;
}
Run Code Online (Sandbox Code Playgroud)

Cer*_*nce 6

看起来toDataURL是异步的,回调为主-要么改变它,以便它返回一个PromiseawaitPromise,或传递Promiseresolve步入回调:

async function getBase64() {
  const urls = ['https://i.imgur.com/egNg7JU.jpg', 
                'https://i.imgur.com/RLZ7WH1.jpg', 'https://i.imgur.com/qfabBbA.jpg', 
                'https://i.imgur.com/Zuh1KaX.jpg', 'https://i.imgur.com/yD7X6Q1.jpg'];
  const base64urls = [];
  for (const url of urls) {
    const dataURL = await new Promise(resolve => toDataURL(url, resolve));
    base64urls.push(dataURL);
  }
  console.log(base64urls);
  console.log(base64urls[4]);
}
Run Code Online (Sandbox Code Playgroud)

如果您想更改您的toDataURL函数以返回一个 Promise,那么您不必将其视为回调:

function toDataURL(src) {
  return new Promise(resolve => {
    const image = new Image();
    image.crossOrigin = 'Anonymous';

    image.onload = function () {
      const canvas = document.createElement('canvas');
      const context = canvas.getContext('2d');
      canvas.height = this.naturalHeight;
      canvas.width = this.naturalWidth;
      context.drawImage(this, 0, 0);
      const dataURL = canvas.toDataURL('image/jpeg');
      resolve(dataURL);
    };
    image.src = src;
  });
}
Run Code Online (Sandbox Code Playgroud)

进而 const dataURL = await toDataURL(url)