Promise实现多图预加载

Promise正如它的中文意思“承诺”同样,保存着将来会发生事件(通常为异步操做)。Promise避免了“回调地狱”,写法更加接近同步操做。说到同步,我更加喜欢async、await,它们书写更贴近同步操做。数组

图片加载每每是异步的,若是有操做须要等到全部的图片加载完以后再执行,这时候就须要不断的监听全部图片的加载状况。异步

ES5async

利用ES5实现多图预加载,能够经过计数器判断有多少图片加载完成。函数

var count = 0,    // 计数器
    imgs = [];

/*
* (Array)source 图片url
* (Fun)cb 回调
*/
function preLoadImg(source, cb) { source.forEach(function(url, i) { imgs[i] = new Image(); imgs[i].onload = function() { if(++count === source.length) { cb && cb(); } } imgs.src = url; }) }

ES6this

ES6原生提供了Promise对象,接下来用Promise改写上面的代码。url

    // 预处理图片
    function preLoadImg(source){
        let pr = [];
        source.forEach(url => {// 预加载图片
            let p = loadImage(url)
                    .then(img => this.images.push(img))
                    .catch(err => console.log(err))
            pr.push(p);
        })

        // 图片所有加载完
        Promise.all(pr)
                .then(() => {
                    // do sth
                });

    }
    // 预加载图片
    function loadImage(url) {
        return new Promise((resolve, reject) => {
            let img = new Image();
            img.onload = () => resolve(img);
            img.onerror = reject;
            img.src = url;
        })
    }

Promise其实是将回调操做独立出来,当Promise状态从pending(进行中)改成resolved(已完成),then注册的函数就会被执行,若是状态从pending改成rejected(已失败),就会被catch捕获。spa

这里向Promise.all传入了一个数组(能够不是数组,具备iterator接口对象都可以,但返回的成员都必须是Promise实例,若是不是Promise实例,也会调用Promise.resolve转化为Promise实例),数组中的Promise状态均为resolved,Promise.all的状态才会是resolved,不然Promise.all的状态为rejected。也就是说,当全部图片加载完成后,才会执行then中的函数。code

可是,若是参数中的Promise实例本身有定义catch方法,那么当rejected的时候,就会被本身的catch捕获,catch方法执行完后,是会返回一个新的,状态为resolve的Promise实例,所以,传给Promise.all的是这个新的,状态为resolve的Promise。为了防止有图片加载失败,阻塞后续操做,为每个p添加catch,捕获reject,Primise.all就接受不到了。对象

相关文章
相关标签/搜索