调用自定义getImageSize函数获取图片尺寸时数组元素返回undefined的技术问题咨询
Ah, I see the issue here—you're hitting a classic asynchronous operation pitfall! Let me break down what's happening and show you how to fix it.
问题根源
Your getImageSize function returns the size array immediately, but the img.onload callback that populates this array runs after the function has already returned. Image loading is an asynchronous process—it doesn't block the rest of your code from executing, so when you log iconSize right after calling the function, the onload hasn't had a chance to fire yet, leaving you with an empty array.
解决方案:用Promise封装异步操作
We need to rewrite getImageSize to return a Promise that resolves only when the image has finished loading (and thus we have the correct dimensions). Here's the updated function:
getImageSize(fileUploaded: File): Promise<number[]> { return new Promise((resolve, reject) => { const _URL = window.URL || window.webkitURL; const img = new Image(); img.onload = function() { // Clean up the object URL to avoid memory leaks _URL.revokeObjectURL(img.src); // Resolve with the loaded dimensions resolve([this.width, this.height]); }; img.onerror = function() { // Clean up even on error _URL.revokeObjectURL(img.src); // Reject with an error message reject(new Error(`Invalid image file: ${fileUploaded.type}`)); }; img.src = _URL.createObjectURL(fileUploaded); }); }
修改调用逻辑以处理Promise
Since our function now returns a Promise, we need to wait for it to resolve before checking the dimensions. We can use async/await (the cleanest approach) or .then() syntax. Here's how to update your validation code:
// Make sure the containing function is marked as async async validateIconResolution() { try { // Wait for the Promise to resolve and get the actual dimensions const iconSize = await this.utilService.getImageSize(this.icon[0]); console.log(iconSize); // Now logs [512, 512] (or your actual image size) console.log(iconSize.length);// Logs 2 console.log(iconSize[0]); // Logs the width // Run your validation check as intended if(iconSize[0] !== 512 || iconSize[1] !== 512) { this.notifications.create( 'Error', 'Icon resolution must be 512*512', NotificationType.Error, { theClass: "outline primary", timeOut: 6000, showProgressBar: false } ); return; } // If validation passes, proceed with your logic here } catch (error) { // Handle cases where the image failed to load (invalid file, etc.) this.notifications.create( 'Error', (error as Error).message, NotificationType.Error, { theClass: "outline primary", timeOut: 6000, showProgressBar: false } ); } }
额外注意事项
- Always call
_URL.revokeObjectURLafter loading the image—this cleans up the temporary URL created for the file, preventing memory leaks in your application. - Using Promises (and async/await) is the standard way to handle asynchronous operations like image loading in modern JavaScript/TypeScript, ensuring you have access to the data only when it's ready.
- Don't forget to handle errors! The
catchblock will catch any issues with invalid image files, so you can notify the user appropriately.
内容的提问来源于stack exchange,提问作者Teddy Kossoko

