javascript - 使用 Promise() 在 Web 浏览器上加载图像

标签 javascript html5-canvas es6-promise

我正在尝试从 here 学习如何用 JavaScript 制作 SuperMario
有人可以解释以下函数 LoadImage 的流程吗?

function loadImage(url) {
        return new  Promise(resolve => {
            const image = new Image();
            image.addEventListener('load', () => {
                resolve(image);
            });
            image.src = url; 
        });
}

const canvas = document.getElementById('screen');
const context = canvas.getContext('2d');

context.fillRect(0,0,50,50);

loadImage('/img/tiles.png')
.then(image=>{
    context.drawImage(image,0,0);  // the function LoadImage returns a Promise with image object(which is  a constant)
// as parameter and if the promise is fulfilled then the image is drawn. 
/
});

编辑

我确实了解如何使用 => 运算符。
用于使函数的长度更小。
image.addEventListener('load', () => {
                resolve(image);

上面这行表示加载图像时 promise 已履行。
那么这是否意味着执行以下行然后事件监听器正在等待在客户端浏览器中下载图像?
image.scr = url;

下面函数的流程对我来说有点模糊
function loadImage(url) {
        return new  Promise(resolve => {
            const image = new Image();
            image.addEventListener('load', () => {
                resolve(image);
            });
            image.src = url; 
        });

编辑2:

好吧,这是一个愚蠢的帖子。是的,因为来自 url 的 IMAGE 被加载到图像对象中,然后事件监听器启动了 resolve()。

最佳答案

您展示的代码引入了一个异步原语 Promise,它可以被传递并用于访问尚未填充的资源。
在这种情况下,您需要 Image已完全加载并具有您可以使用的图像数据。但是,在获取图像数据的网络请求完成之前,您无法访问图像数据。
例如,这不起作用:

const img = new Image();
img.src = "example.com/house.jpg";
ctx.drawImage(img, 0, 0); // img isn't done loading yet

相反,我们必须 等待直到加载完成。有很多方法可以做到这一点,但最常见的约定是使用、回调、Promises 或 async/await。
您展示的方法结合了回调和 Promises(非必要)。
让我们分解代码:

/**
 * Load an image from a given URL
 * @param {String} url The URL of the image resource
 * @returns {Promise<Image>} The loaded image
 */
function loadImage(url) {
  /*
   * We are going to return a Promise which, when we .then
   * will give us an Image that should be fully loaded
   */
  return new Promise(resolve => {
    /*
     * Create the image that we are going to use to
     * to hold the resource
     */
    const image = new Image();
    /*
     * The Image API deals in even listeners and callbacks
     * we attach a listener for the "load" event which fires
     * when the Image has finished the network request and
     * populated the Image with data
     */
    image.addEventListener('load', () => {
      /*
       * You have to manually tell the Promise that you are
       * done dealing with asynchronous stuff and you are ready
       * for it to give anything that attached a callback
       * through .then a realized value.  We do that by calling
       * resolve and passing it the realized value
       */
      resolve(image);
    });
    /*
     * Setting the Image.src is what starts the networking process
     * to populate an image.  After you set it, the browser fires
     * a request to get the resource.  We attached a load listener
     * which will be called once the request finishes and we have
     * image data
     */
    image.src = url;
  });
}

/*
 * To use this we call the loadImage function and call .then
 * on the Promise that it returns, passing a function that we
 * want to receive the realized Image
 */
loadImage("example.com/house.jpg").then(houseImage => {
  ctx.drawImage(houseImage, 0, 0);
});


不过老实说,loadImage函数可能会更健壮一些,因为它现在不处理错误。考虑以下增强:

const loadImage = (url) => new Promise((resolve, reject) => {
  const img = new Image();
  img.addEventListener('load', () => resolve(img));
  img.addEventListener('error', (err) => reject(err));
  img.src = url;
});

loadImage("example.com/house.jpg")
  .then(img => console.log(`w: ${img.width} | h: ${img.height}`))
  .catch(err => console.error(err));

关于javascript - 使用 Promise() 在 Web 浏览器上加载图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52059596/

相关文章:

javascript - 将 jqWidgets 组合框限制为值列表

javascript - 从background.js发送到contentScript.js

javascript - 加载图像后重定向

javascript - 遍历 DOM 对象以查找特定元素

javascript - HTML5 Canvas 上的图像仅出现一帧

javascript - 获取模拟 : GLOBAL is not defined

JavaScript 图像仅在刷新时加载

android - HTML5 Canvas元素不会出现在已编译的Android Ionic中,但可以在浏览器“Ionic Serve”中使用

javascript - Nodejs Promise reject 不会转发错误消息

javascript - Promise.all 返回更多值