图像加载中的异步等待

IT技术 javascript ecmascript-6 async-await
2021-03-19 22:14:26

临时文件

export default class Temp {
    async addImageProcess(src){
        let img = new Image();
        img.src = src;
        return img.onload = await function(){
          return this.height;
        }
    }
}

另一个文件.js

import Temp from '../../classes/Temp'
let tmp = new Temp()

imageUrl ="https://www.google.co.in/images/branding/googlelogo/2x/googlelogo_color_120x44dp.png"
let image = tmp.addImageProcess(imageUrl);
console.log(image)

以上是我的代码。我有一个图像 url 并尝试使用 async await 获取图像的属性,但它不起作用,不明白我错过了什么。

3个回答

您这里的问题来自...的定义await

await运算符用于等待Promise

Image.prototype.onload财产不是一个Promise,您也不是将其分配给它。如果你想height在加载后返回属性,我会创建一个Promise......

addImageProcess(src){
  return new Promise((resolve, reject) => {
    let img = new Image()
    img.onload = () => resolve(img.height)
    img.onerror = reject
    img.src = src
  })
}

然后,您将使用以下内容访问该值

tmp.addImageProcess(imageUrl).then(height => {
  console.log(height)
})

或者,如果在一个async函数内

async function logImageHeight(imageUrl) {
  console.log('height', await tmp.addImageProcess(imageUrl))
}
谢谢@phil,现在我明白了。addImageProcess 中有一个小错误。
2021-05-02 22:14:26

以前的答案是正确的,但我想指出现在有一种HTMLImageElement.decode()方法几乎对应于 Promisified onload 处理程序。

这样做的优点是不需要自己包装,处理已经加载的图像(以前的答案在这种情况下失败),并等待图像被实际解码,这在各种情况下可能是一件好事(例如,如果你如果想将它与同步 Canvas2DContext.drawImage()方法一起使用,则在解码完成时您的脚本将被阻止)。

所以现在只需要

(async () => {
  const img = new Image();
  img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png";
  await img.decode();
  // img is ready to use
  console.log( `width: ${ img.width }, height: ${ img.height }` );
})();

其他答案可能是正确的,但这个答案干净而优雅。
2021-04-30 22:14:26
这绝对是现代 Web 开发者更好的答案。
2021-05-11 22:14:26

虽然提议的解决方案完美无缺,但我希望能够避免为每个异步函数编写Promise,因此我为此编写了一个通用实用程序函数:

在 JavaScript 中

function onload2promise(obj){
    return new Promise((resolve, reject) => {
        obj.onload = () => resolve(obj);
        obj.onerror = reject;
    });
}

在typescript中(包括一些通用类型检查):

interface OnLoadAble {
   onload: any;
}
function onload2promise<T extends OnLoadAble>(obj: T): Promise<T> {
   return new Promise((resolve, reject) => {
   obj.onload = () => resolve(obj);
   obj.onerror = reject;
 });
}

在问题的示例中,您现在可以执行以下操作:

async function addImageProcess(src){
    let img = new Image();
    let imgpromise = onload2promise(img); // see comment of T S why you should do it this way.
    img.src = src;
    await imgpromise;
    return this.height;
}

当然,anotherfile.js 中的调用仍然应该异步发生,如 Phils answer 的最后一个代码块中所述

你的方法有点危险:它onload在图像加载开始后设置参见stackoverflow.com/questions/14648598/...
2021-05-10 22:14:26
好的评论,我想我更新了答案以解决您提到的问题!
2021-05-14 22:14:26
好的!还有一些想法:onabort应该拒绝Promise吗?所述interface OnLoadAble应包含onerror(和onabort如果添加作为拒绝事件)。在您的上一个 Codeblock 中,您的意思是return img.height;
2021-05-17 22:14:26
Promise从不拒绝。设置onerrorfunction onload2promise(obj){ return new Promise((resolve,reject) => { obj.onload = () => resolve(obj); obj.onerror = reject; }); }
2021-05-20 22:14:26