Wie gehen Sie mit der Asynchronität beim Laden von Leinwandbildern in HTML5 um?

Ich habe etwas über HTML5's Canvas gelernt. Da das Laden von Bildern eine Weile dauern kann, scheint die Verwendung von @ die geeignete Technik zu seionload, um zu warten, bis das Bild geladen ist, bevor Sie versuchen, es zu zeichnen. So

<canvas id="fig" width="400" height="400"></canvas>

var fig = document.getElementById('fig1');
var ctx = fig.getContext('2d');

var img = new Image();
img.onload = function() { ctx.drawImage(img, 300, 100); };
img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';

Es ist jedoch wahrscheinlich, dass der folgende Code ausgeführt wird, bevor die Onload-Funktion das @ ausführen kandrawImage(), was möglicherweise zu unerwünschtem Verhalten führt:

ctx.translate(0,400); ctx.scale(1,-1);   /* switch to lower-left as origin */
/* if onload happens after here, it uses new coordinate system! */
ctx.beginPath();
ctx.moveTo(10, 20);
ctx.lineTo(290, 30);
ctx.stroke();

Sicher gibt es eine vernünftige Art, damit umzugehen und alles in der Onload-Funktion zu tun scheint unsinnig).

========================= EDIT BELOW ====================== ===

Hier ist eine Änderung an meinem Code mit einem einzigen Versprechen, um die Idee so einfach wie möglich zu veranschaulichen.

var img = new Image();
var promise = new Promise(                         // make a promise
        function(resolve, reject) {
                img.onload = function() {
                        ctx.drawImage(img, 300, 100);   
                        resolve();     // keep the promise -- lets the "then" proceed
                };      
                img.src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
        }
);

// .then() waits for the promise to be resolved (see also .catch for rejection)
promise.then( function() {
        ctx.translate(0,400); ctx.scale(1,-1);
        ctx.beginPath();
        ctx.moveTo(10, 20);
        ctx.lineTo(290, 30);
        ctx.stroke();
});

Antworten auf die Frage(4)

Ihre Antwort auf die Frage