[英]Javascript: Strange behavior when using promises, async-await, returns “Promise <pending>”
[英]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
,它在圖像loads
時resolves
,然后在畫布上下文中繪制它: 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.