fezaoduke / fe-practice-hard

晚练课
69 stars 6 forks source link

第 47 期(技巧):图片加载器 #50

Open wingmeng opened 5 years ago

wingmeng commented 5 years ago

题目:

请编写一个名为 ImageLoader 的图片加载器,接收一个数组或字符串参数,包含图片的 URL 地址,当所有图片加载完毕时,触发 onReady 回调。

测试用例:

const imgUrls = [
  'https://cdn.pixabay.com/photo/2019/04/29/14/50/camogli-4166255__340.jpg',
  'https://cdn.pixabay.com/photo/2019/06/24/15/31/forest-4296305__340.jpg',
  'https://cdn.pixabay.com/photo/2019/06/27/03/42/beach-4301479__340.jpg',
  'https://cdn.pixabay.com/photo/2019/06/19/23/13/plum-blossoms-4285819__340.jpg',
  'https://cdn.pixabay.com/photo/2019/05/19/23/47/clouds-4215608__340.jpg',
  'https://cdn.pixabay.com/photo/2018/10/18/11/29/waterfowl-3756126__340.jpg'
];
const loader = new ImageLoader(imgUrls);
loader.onReady = () => {
  console.log('图片全部加载完毕');
}

参考答案:

class ImageLoader {
  constructor(urls) {
    this.cache = {};

    if (Array.isArray(urls)) {
      urls.forEach(url => this.load(url));
    } else {
      this.load(urls);
    }
  }

  load(url) {
    if (this.cache[url]) {
      return this.cache[url];
    }

    let img = new Image();

    img.addEventListener('load', _ => {
      this.cache[url] = img;

      if (this.isReady()) {
        this.onReady();
      }
    });

    this.cache[url] = false;
    img.src = url;
  }

  isReady() {
    for (let k in this.cache) {
      if (!this.cache[k]) {
        return false;
      }
    }

    return true;
  }

  onReady(fn) {
    typeof fn === 'function' && fn();
  }
}