簡體   English   中英

在 JavaScript 中使用 Promises 和 async-await 一一加載圖像

[英]Load images one-by-one using Promises and async-await in JavaScript

期望的結果:我希望圖像(圖像和圖像 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 ,它在圖像loadsresolves ,然后在畫布上下文中繪制它:

     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) ,如在推薦的這篇文章和,

  • c.drawImage.call ,在這種情況下,我將resolve更改為resolve(c, img, 0, height, 100, 60)

    但是,他們都沒有成功!

    我做錯了什么?

  • 你的 loadImages 返回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>

    但是,如果可以的話,您的代碼遠非清晰......您可能會通過更冗長而獲勝,並以不同的方式拆分您的邏輯:
    首先處理加載資產,然后處理您的渲染對象(這里是您傳遞給 drawImage 的參數)。

    混合兩者只會使您的代碼更難維護。

    此外,您的名為height的變量可能最好稱為y

    暫無
    暫無

    聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

     
    粵ICP備18138465號  © 2020-2024 STACKOOM.COM