如何同步加载图像

How do I make an image load synchronously?

本文关键字:加载 图像 同步 何同步      更新时间:2023-09-26

我想创建一个具有image属性的对象,但我希望只有在加载图像后,contstructor才能完成运行。或者用代码描述:

GraphicObject = Class.extend({
    //This is the constructor
    init: function(){
          this.graphic = new Image();
          this.graphic.src = 'path/to/file.png';
          while(true)
          {
              this.graphic.onload = function(){break;};
              //I know this won't work since the 'break' is on a different context
              //but you got what I try to do.
          }
     }

})

对于那些不熟悉我在脚本中使用的Class表示法的人来说,它是基于这个的

有什么想法吗?

这是可能的,但只有使用Base64数据URL古代艺术

GIF图像转换为Base64。

rune.b64

R0lGODlhIwAjAIAAAP///wAAACwAAAAAIwAjAAACf4SPqcsb3R40ocpJK7YaA35FnPdZGxg647kyqId2SQzHqdlCdgdmqcvbHXKi4AthYiGPvp9KVuoNocWLMOpUtHaS5CS54mZntiWNRWymn14tU7c2t6ukOJlKR5OiNTzQ7wb41LdnJ1coeNg3pojGqFZniPU4lTi0d4mpucmpUAAAOw==

JavaScript,它通过阻塞AJAX从同一服务器加载转换后的图像。

loader.js

var request = new XMLHttpRequest();
var image = document.createElement('img');
request.open('GET', 'rune.b64', false);
request.send(null);
if (request.status === 200) {
  image.src= 'data:image/gif;base64,' + request.responseText.trim();
  document.getElementsByTagName("body")[0].appendChild(image); 
}

问题

  • 一些较旧的浏览器不喜欢(大)数据URL
  • Base64编码使图像放大约37%
  • 整个UI被阻止,直到加载图像

这是非常邪恶的方式

有一种非邪恶的方法可以同步加载Javascript中的图像。

loadImage = async img => {
    return new Promise((resolve, reject) => {
        img.onload = async () => {
            console.log("Image Loaded");
            resolve(true);
        };
    });
};

在任何地方都可以用await来称呼它。像这个

for(let i=0;i<photos.length;i++){
    await loadImage(photos[i]);
}

它将逐个加载所有图像。

注意:调用函数必须是async才能使用await

将依赖代码放入回调中没有其他非邪恶的方式

GraphicObject = Class.extend({
    //This is the constructor
    init: function(){
          this.graphic = new Image();
          this.graphic.onload = function ()
          {
              // the rest of the ctor code here
          };
          this.graphic.src = 'path/to/file.png';
     }
});
var timeOut = 5*1000; //ms - waiting for max 5s to laoad
var start = new Date().getTime();
while(1)
  if(img.complete || img.naturalWidth || new Date().getTime()-start>timeOut)
    break;

基于这个答案。

我把它封装到函数中,它成功了!

for (var i = 0, i < asset.length; i++) {
    var img = new Image();
    img.src = "file:///" + folder + "/" + asset[i].name;
    getWdrp(img);
    function getWdrp (img) {
        img.onload = function(){
            // work with the image file
        }
    }
}

这是一个对我有用的例子,因为以前,当我在不包装函数的情况下处理图像时,它是异步的,现在是异步的。