加载图像有时会导致图像被加载两次

时间:2018-08-10 10:42:32

标签: javascript

我正在使用图像预加载工具,但是遇到一个奇怪的问题,每当我提供多个图像进行加载时,有时第一个图像都会被处理两次。

我知道它会被处理两次,因为最后,当应该完成加载时,我将数组记录到控制台,有时甚至记录到了它:

(2) [img] [img]

(就像它应该的那样),如果我不断刷新,我有时会遇到:

(2) [img] [img]
(3) [img] [img]

下面是产生该结果的代码。我不明白为什么有时它返回正确的值,而有时却不返回正确的值。如果您多次在以下代码段中运行该代码段,则可能会出现其中一次不良结果。

似乎loadComplete()被击中了两次,这很令人困惑,因为它后面有一个return,所以我看不出它可以被多次调用。

class Load {

  constructor() {
    this.queue = [];
    this.completed = [];
    this.totalItems = 0;
    this.itemsCompleted = 0;
  }

  image(src) {
    return this.addToQueue(src);
  }

  addToQueue(src) {
    let item = {
      src: src,
      loaded: false
    };

    this.queue.push(item);
    this.totalItems++;

    return this;
  }

  addToCache() {
    for (let i = 0; i < this.queue.length; i++) {

      let item = this.queue[i];

      if (item.loaded) {
        this.queue.splice(i, 1);
        i--;

        this.itemsCompleted++;

        break;

      }

      this.loadImage(item);

    }

    if (this.itemsCompleted == this.totalItems) {

      this.loadComplete();

      return;

    }
  }

  start() {
    this.addToCache();
  }

  loadImage(item) {
    item.data = new Image();

    item.data.addEventListener('load', () => {
      this.completed.push(item.data);

      item.loaded = true;

      this.addToCache();
    });

    item.data.addEventListener('error', (err) => {
      console.log(err);
    });

    item.data.src = item.src;
    item.data.crossOrigin = 'anonymous';
  }

  loadComplete() {
    console.log(this.completed);
  }

}


let load = new Load();

load.image('https://i.imgur.com/fHyEMsl.jpg');

load.image('https://i.imgur.com/fHyEMsl.jpg');

load.start();

1 个答案:

答案 0 :(得分:1)

问题是您以异步方式更新了完整文件,因此此处未正确计数(这是一个更正示例)(很抱歉,这有点混乱,但您可以理解)。希望对您有帮助

class Load {

  constructor() {
    this.queue = [];
    this.completed = [];
    this.totalItems = 0;
    this.itemsCompleted = 0;
  }

  image(src) {
    return this.addToQueue(src);
  }

  addToQueue(src) {
    let item = {
      src: src,
      loaded: false
    };

    this.queue.push(item);
    this.totalItems++;

    return this;
  }

  addToCache() {
    for (let i = 0; i < this.queue.length; i++) {

      let item = this.queue[i];

      if (item.loaded) {
        this.queue.splice(i, 1);
        i--;

        this.itemsCompleted++;

        break;

      }

      this.loadImage(item);

    }
    
  }
  loadCompleted(){
  if (this.completed.length == this.totalItems) {

      this.loadComplete();

      return;

    }
  }

  start() {
    this.addToCache();
  }

  loadImage(item) {
    item.data = new Image();

    item.data.addEventListener('load', () => {
      this.completed.push(item.data);
      this.loadCompleted();
    });
          item.loaded = true;

    item.data.addEventListener('error', (err) => {
      console.log(err);
    });

    item.data.src = item.src;
    item.data.crossOrigin = 'anonymous';
  }

  loadComplete() {
    console.log(this.completed);
  }

}


let load = new Load();

load.image('https://i.imgur.com/fHyEMsl.jpg');

load.image('https://i.imgur.com/fHyEMsl.jpg');

load.start();