web-dev-qa-db-fra.com

async attendre dans le chargement de l'image

Temp.js

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

autrefichier.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)

Ci-dessus est mon code. J'ai une URL d'image et j'ai essayé d'obtenir les propriétés de l'image en utilisant async, mais cela ne fonctionne pas, je ne comprends pas ce que j'ai manqué.

14
Rahul

Votre problème ici s'étend de la définition de await ...

L'opérateur await est utilisé pour attendre un Promise

Le Image.prototype.onload la propriété n'est pas une promesse, et vous ne lui en attribuez pas une. Si vous souhaitez renvoyer la propriété height après le chargement, je créerais plutôt un Promise...

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

Vous utiliseriez ensuite ce qui suit pour accéder à cette valeur

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

ou, si dans une fonction async

async function logImageHeight(imageUrl) {
  console.log('height', await tmp.addImageProcess(imageUrl))
}
28
Phil

Bien que la solution proposée fonctionne parfaitement, je veux pouvoir éviter d'écrire des promesses pour chaque fonction asynchrone, j'ai donc écrit une fonction utilitaire générique juste à cette fin:

en javascript

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

en TypeScript (y compris certains contrôles de caractères génériques):

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;
 });
}

Dans l'exemple de la question, vous pouvez maintenant faire:

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;
}

Bien sûr, l'appel dans anotherfile.js devrait toujours se faire de manière asynchrone également, comme expliqué dans le dernier bloc de code de la réponse de Phils.

7
Pinna_be