【问题标题】:How do I make an image load synchronously?如何使图像同步加载?
【发布时间】:2012-02-23 20:59:21
【问题描述】:

我想创建一个具有图像属性的对象,但我希望构造函数仅在加载图像后完成运行。或者用代码来描述:

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


})

对于那些不熟悉我在脚本中使用的类表示法的人,它基于this

有什么想法吗?

【问题讨论】:

  • 所以您真的希望图像在加载之前阻止所有 JavaScript(以及所有用户交互)
  • 是的。我想知道如果创建了对象,则加载其中的图形。我尝试使用“在对象的每个实例的回调中设置一个标志”,但是在为每个单独的类执行此操作后,我正在扩展它开始变老,我开始寻找一种更自动的方法来做到这一点......
  • 只询问图像是否已加载就足够了吗?图像有一个.complete 属性,在加载时设置为true,所以如果有一些代码需要处理图像,但只有在加载时,它可以检查该属性,然后在每个n 重试加载前的毫秒数。
  • 在这个特定的用例中,我想创建一堆 GraphicObjects,除非它们都被加载,否则不会开始任何交互。如果甚至无法加载,应用程序根本不应该运行。应用程序初始化后不会创建任何 GraphicObject。我知道我可以检查文件是否已加载,但我宁愿知道“如果它运行,它已加载”,因为我很懒并且厌倦了一直编写回调:P
  • 嗯,明白了...如果由于某种原因图像没有出现,浏览器可能会锁定...我想我会创建一个预加载器对象...我的问题被视为已回答!

标签: javascript html


【解决方案1】:

这是可能的,但仅限于 Base64Data-URL古代艺术

GIF 图片转换为 Base64。

符文.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 都被阻塞

这是一种非常邪恶的方式

【讨论】:

  • +1 因为,嘿,它确实回答了这个问题;你警告说它是邪恶的(它是)。
  • 为了记录,这仍然是异步加载实际图像src。
  • 真的吗?当我将console.log(image.complete);console.log(image.naturalWidth) 直接放在image.src = 后面时,输出表明图像已加载。
  • @Naatan, K.. 你有证据/数据证明你的主张吗?行为是否取决于浏览器/图像大小?有什么限制吗?这是在某处指定的吗?
  • XMLHttpRequest 的 always 以异步方式完成它们的工作。
【解决方案2】:

在 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

【讨论】:

  • 我一直在网上搜索这个!谢谢
  • 使用asyncawait 的要求意味着根据定义,这不是同步的。
  • await 关键字使其同步。它在移动到下一行之前等待当前行执行完成。
  • 使用 image.decode() 可能比使用 onload 回调更优雅,虽然结果可能是一样的。
【解决方案3】:

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

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

【讨论】:

  • 你说“非邪恶”是什么意思?
  • Javascript 是单线程的,如果不锁定用户浏览器,你就不能做你想做的事。如果有任何代码需要在构造后访问对象属性,请让构造函数接受 onload 参数并在图像加载后调用它。
  • “非邪恶”是夸大其词。对于某些人来说,将函数包装在数千个不同的回调中可能不是最好的解决方案。
  • 他说“没有其他非邪恶的方式”很有趣,但他的答案比他高出 2 个点。使用承诺...这是 2020 年
  • @MisterSirCode javascript promises 和 await 在八年前写这个答案时并不存在。时代变了:)
【解决方案4】:
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;

基于this 的回答。

【讨论】:

  • 这解决了问题并恢复了正确的功能,但是随着 Promise 的出现,请注意我们现在可以将 img.onload 包装在 Promise 中并 await() 它!技术进步的乐趣。
  • 这非常邪恶,但我认为这是唯一真正同步的答案
【解决方案5】:

我把它包装成函数,它起作用了!

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

这是一个对我有用的例子,因为之前,当我在处理图像而不包装函数时,它会异步工作,现在它是异步的。

【讨论】:

    猜你喜欢
    • 2010-11-12
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    相关资源
    最近更新 更多