代码之家  ›  专栏  ›  技术社区  ›  vrintle Jake

在JavaScript中使用Promissions和async Wait逐个加载图像

  •  -1
  • vrintle Jake  · 技术社区  · 7 年前

    预期结果: 我希望图像(图像和图像2)应该加载 一个接一个

    'use strict';
    
    window.addEventListener('DOMContentLoaded', () => {
      const cvs = document.querySelector('#cvs');
      cvs.width = window.innerWidth;
      cvs.height = window.innerHeight;
      const c = cvs.getContext('2d');
    
      let image = new Image(); // first image
      image.src = 'https://images5.alphacoders.com/559/559956.jpg';
      let image2 = new Image(); // second image
      image2.src = 'https://www.highreshdwallpapers.com/wp-content/uploads/2013/03/Avengers-A.jpg';
      let y = 0;
    
      let loader = img => new Promise(resolve => img.onload = resolve(img, 0, y, 100, 60));
      let logger = img => new Promise(resolve => img.onload = resolve(img.src + ' loaded!'));
    
      async function loadImages() {
        await logger(image).then(console.log); // this works
        await logger(image2).then(console.log); // this works
    
        await loader(image).then(c.drawImage);
        y += 60;
        await loader(image2).then(c.drawImage);
      };
      
      loadImages();
    });
    body {
      margin: 0;
    }
    
    #cvs {
      position: fixed;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Page Title</title>
      <link rel="stylesheet" type="text/css" href="./style.css">
    </head>
    
    <body>
      <canvas id='cvs'>Canvas not supported</canvas>
      <script type="text/javascript" src='./script.js'></script>
    </body>
    
    </html>

    以下是我的想法:

  • 我创建了一个返回 new Promise 哪一个 resolves 当图像 loads 然后在画布上下文上绘制它:
    let loader = img => new Promise(resolve => img.onload = resolve(img, 0, height, 100, 60));
    

  • 然后,我创建一个 asynchronous loader 每一张图片 并将其绘制在画布上:
    async function loadImages() {
        // ...
        await loader(image).then(c.drawImage);
        y += 60;
        await loader(image2).then(c.drawImage);
    };
    

    但是 ,由于某些原因,代码不起作用。我得到了以下错误: Uncaught (in promise) TypeError: Illegal invocation .

    我试着换了 c.drawImage

  • c.drawImage.bind(c) ,如 this post 以及,

  • c.drawImage.call ,在这种情况下,我更改了 resolve 作为 resolve(c, img, 0, height, 100, 60)

    但是,他们两个都没有成功!

    我做错了什么?

  • 1 回复  |  直到 7 年前
        1
  •  1
  •   Kaiido    7 年前

    undefined (因为您没有明确返回任何内容),所以 drawImage 我什么都不会做。

    尽管还不完全清楚你想做什么,但我觉得你想在这幅画中画两幅图像 then() .

    为了尽可能少地修改代码,您可以在一个数组中返回两个图像,然后在数组中迭代该数组并对其调用drawImage。
    您还必须将所有参数作为数组传递到 loader 功能。

    另外,请注意,您在 img.onload = resolve(.. ,应该是 img.onload = e => resolve(... ,否则 resolve 直接被调用。

    还要记住,onload事件只会触发一次,所以一旦您等待它,它就不会再次发生(除非您强制它)。

    window.addEventListener('DOMContentLoaded', () => {
      const cvs = document.querySelector('#cvs');
      cvs.width = window.innerWidth;
      cvs.height = window.innerHeight;
      const c = cvs.getContext('2d');
    
      let image = new Image(); // first image
      image.src = 'https://images5.alphacoders.com/559/559956.jpg';
      let image2 = new Image(); // second image
      image2.src = 'https://www.highreshdwallpapers.com/wp-content/uploads/2013/03/Avengers-A.jpg';
      let height = 0;
    
      let loader = img => new Promise(resolve => {
        // resolve the arguments as an Array
        img.onload = e => resolve([img, 0, height, 100, 60]);
        // force resetting the src, otherwise onload may already have fired
        img.src = img.src;
      });
    
      async function loadImages() {
        const a = await loader(image);
        height += 60;
        const b = await loader(image2);
        // you must return something if you it to be passed in the then()
        return [a, b];
      };
    
      loadImages().then(arr => {
        arr.forEach(args => c.drawImage.apply(c, args));
      }).catch(console.error);
    });
    <canvas id='cvs'>Canvas not supported</canvas>

    但如果我可以的话,你的代码还很不清楚。。。你可能会通过更详细的措辞和不同的逻辑来获胜:
    加载DrawAssets(然后在此处传递处理渲染对象)。

    两者的混合只会使代码更难维护。

    另外,您的变量名为 height 可能会更好 y