11-利用Promise的图片异步加载 / Promise封装ajax,模拟axios / Promise的finally原理

Promise的图片异步加载其实就是利用了宏任务先执行,后执行微任务:

new Promise()的时候,Promise新建后就会立即执行

 利用这一特性,我们可以创建Promise对象的时候,创建image标签,然后再给img标签的 src赋值路径,这样在then的回调函数中,把其加入到盛放显示图片的盒子中,盒子中原来展示是一个缺省图,等到图片加载好了,就显示真正的图片:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 
 4 <head>
 5     <meta charset="UTF-8">
 6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
 7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 8     <title>Document</title>
 9 </head>
10 <style>
11     h1 {
12         display: block;
13     }
14 </style>
15 
16 <body>
17     <div id='box'>
18         <h1>我是一张缺省图</h1>
19     </div>
20 </body>
21 
22 </html>
23 <style>
24 
25 </style>
26 <script>
27     var oBox = document.getElementById('box');
28     var oH = document.querySelector('h1')
29 
30     function loadImageAsync(url) {
31         return new Promise(function(resolve, reject) {
32             var image = new Image();
33 
34             image.onload = function() {
35                 resolve(image);
36             };
37 
38             image.onerror = function() {
39                 reject(new Error('Could not load image at ' + url));
40             };
41 
42             image.src = url;
43         });
44     }
45     // 模拟一下异步加载图片
46     // 用setTimeoutm模拟ajax调用接口,获取接口返回的图片路径,然后传入函数中,函数中已经提前创建好了
47     // 图片标签。我们在.then的回调函数中自行决定插入div容器中做一些事,比如把缺省图隐藏掉
48     setTimeout(() => {
49         loadImageAsync('./lion.jpg').then(res => {
50             oH.style.display = 'none';
51             oBox.appendChild(res);
52         })
53     }, 1000)
54 </script>

 1秒后显示图片:


 Promise封装ajax

 1    function myAxios(url) {
 2         return new Promise((resolve, reject) => {
 3             let http = new XMLHttpRequest();
 4             http.open('GET', url)
 5             http.onreadystatechange = function() {
 6                 if (this.readyState !== 4) {
 7                     return
 8                 }
 9                 if (this.status === 200) {
10                     resolve(this.response)
11                 } else {
12                     reject(new Error(this.txt))
13                 }
14             }
15             http.send();
16         })
17     }
18 
19     myAxios('').then(res => {
20         // 拿到数据
21     }).catch(err => {
22         // 捕获错误
23     })

Promise的finally原理

 finally中的函数无参数的情况:

  Promise.prototype.Myfinally = function(callback) {
        let P = this.constructor;
        return this.then(
            // 正常情况
            () => P.resolve(callback()),
            () => P.resolve(callback())
        );
    };

    function promiseFn(flag) {
        return new Promise((resolve, reject) => {
            if (flag) {
                resolve('正确')
            } else {
                reject('错误')
            }
        })
    }
    promiseFn(false).then(res => {
        console.log(res, '我是success');
    }).catch(err => {
        console.log(err, "我是err");
    }).Myfinally(res => {
        // console.log(res, '结果'); //不传参,这里就没有res,输出undefined
        console.log('我是finally');
    })

有参数的情况,直接把成功时或者失败时候的参数传给finally的回调函数,这样一个finally中的那一个参数,既可以捕获到失败也可以捕获到成功

  Promise.prototype.Myfinally2 = function(callback) {
        let P = this.constructor;
        return this.then(
            // 传参的情况
            value => P.resolve(callback(value)),
            reason => P.resolve(callback(reason))
        );
    };

    function promiseFn2(flag) {
        return new Promise((resolve, reject) => {
            if (flag) {
                resolve('正确')
            } else {
                reject('错误')
            }
        })
    }
    // 传参就可以用finally方法,finally里面的参数是res,也可以是err
    promiseFn2(true).Myfinally2((res) => {
        // res可以是原有的then成功的结果,又可以是catch失败的结果
        console.log(res, '我是结果');
    })
原文地址:https://www.cnblogs.com/haoqiyouyu/p/14716425.html