我正在尝试从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);
以上一行表示在加载图像时实现了承诺。 那么这是否意味着执行以下行,然后事件侦听器正在等待在客户端浏览器中下载图像?
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()。
答案 0 :(得分:6)
您所显示的代码引入了一个异步原语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
函数可能更健壮,因为它现在不处理错误。考虑以下增强功能:
function loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.addEventListener("load", () => resolve(img));
img.addEventListener("error", err => reject(err));
img.src = src;
});
};
loadImage("example.com/house.jpg")
.then(img => console.log(`w: ${img.width} | h: ${img.height}`))
.catch(err => console.error(err));