zoukankan      html  css  js  c++  java
  • Promise (1) 如何使用Promise

    Promise 也是面试高频问题, 今天我们来看看Promise是什么, 能做什么, 怎么用, 下一期我们自己来模拟一个myPromise

    1  Promise 是什么  

    我们要学会自己给自己提问, 才能加深我们的理解, 首先 Promise 是一个类, 类(class)是ES6 一个新的概念 ,和ES5的构造函数相似, 

    但不完全一样,

    类必须通过 new 操作符 调用 ;

    子类通过super() 关键字 来产生this , 在super()之前不能使用this ;

    类上有静态属性 和 静态方法 , 并且子类可以继承父类的静态属性和静态方法 ;

    Promise 中文 译 为 承诺  ,承诺就是说出来的话不会改变, 

    Promise 一旦状态发生变化后就不会再变了 ,比如:

    const p = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(1);
            reject('reject');
            resolve('resolve')
        }, 2000);
    }).then((data) => {
        console.log(data + '-suc')   // 状态为 resolved 触发
    }, (err) => {
        console.log(err + '-err')   // 状态为 rejected  触发
    });

    结果:两秒后打印  1   ,  reject-err

     由此可见  , 由于reject() 方法 先把 promise 的 状态  由 pendding  变为 rejected  , 

    所以状态就是rejected , 后面再执行resolve() 方法也没用了, 状态只改变一次。

    2  Promise 能做什么

    Promise 是为了解决异步回调地狱而出现的, 就是解决那种回调函数中嵌套回调函数的情况。。。。

    它可以把这种异步操作以同步操作的流程表达出来, 一个经典的图片加载例子:

    function loadImg(src) {
        const p = new Promise((resolve, reject) => {
            const image = document.createElement('img'); // 创建image标签
            image.src = src;  // 开始加载
            image.onload = () => {  // 加载成功的回调
                resolve(image); // 成功把image返回
            };
            image.onerror = () => {  // 加载失败的回调
                reject(new Error('url not found')); // 失败丢出error
            }
        });
        return p;
    }
    loadImg('https://timgsa.baidu.com/timg' +
        '?image&quality=80&size=b9999_10000&sec=1554215359089&di=173ff60aee0bcc177d33dced2c88b2ed' +
        '&imgtype=0&src=http%3A%2F%2Fgss0.baidu.com%2F-fo3dSag_xI4khGko9WTAnF6hhy%2Fzhidao%2Fpic%' +
        '2Fitem%2F55e736d12f2eb9388d4c2ebad9628535e5dd6f50.jpg').then((data) => {
        document.body.appendChild(data);   //  成功 把 image 标签 插入 body
        data.style.width = '800px';
        data.style.height = '600px';
    }).catch((err) => {
        console.log(err);  // 失败打印出错误
    });

    效果图:

    把 图片加载 和  加载成功后的数据处理函数   以   同步操作表达出来    , 而不是把数据处理函数

    嵌套在图片加载成功的函数里。

    3 Promise 的其他注意事项

      1. resolve函数 和 reject 函数 里 都可以传参  , reject里一般传Error的实例,

       resolve 里 除了可以传 正常的值 还可以传另一个Promise实例,比如:

    const P1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('出错啦'))
        }, 4000);
    });
    const P2 = new Promise ((resolve, reject) => {
        setTimeout(() => {
            resolve(P1)
        }, 1000);
    });
    P2.then((data) => {
        console.log(data);
    }, (err) => {
        console.log(err)
    });

    结果:     4 秒 打印出 错误信息

     有的小伙伴可能会有疑问,P2 不是执行resolve函数了吗, 为什么打印出的是error 呢 ? 

    我们重头开始分析, P1 创建 并 立即 执行 , 4秒后 P1 执行 reject ()  ;

          然后 P2 创建 并立即执行 , 1 秒后  执行 resolve();

          1 秒钟 到了 , P2 执行 resolve(), 但是 P2 的 resolve 返回的是 P1, 

          那么后面 P2.then 和  P2 其实就没什么 关系 了 , 它 就和 P1 的状态 绑定 在 一起 了 ,

          4 秒钟 到了 , P1 的状态 变成 rejected  , P2.then 打印 error  

    我们再来一个 例子验证  :

    const P2 = new Promise ((resolve, reject) => {
        setTimeout(() => {
            resolve(new Promise((suc, err) => {
                
            }))
        }, 1000);
    });
    P2.then((data) => {
        console.log(data);
    }, (err) => {
        console.log(err)
    });

    结果 : 控制台没有任何输出   

    为什么 呢? P2.then 依赖  resolve()里 返回的 Promise 对象 的 状态  , 

    而  我 没有 调用  任何 改变 其 状态 的api   , 所以 它 的状态 一直是 pendding  ,

    所以没有输出。

    3 Promise 上的静态方法

      ①   Promise.all()

      它接受一个由Promise对象组成的数组, 只有数组中所有Promise的状态都为resolved时才会调用成功的回调,

      只要有一个状态为rejected, 遇到第一个状态变为rejected时, 就会调用失败的回调;

      例子:  

    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
        }, 2000);
    });
    const p2 = new Promise((resolve, reject) => {
        resolve(2);
    });
    const p3 = new Promise((resolve, reject) => {
        resolve(3);
    });
    
    Promise.all([p1, p2, p3]).then((data) => {
        console.log(data);   //  2 秒后输出[1, 2, 3]
    }).catch((error) => {
        console.log(error)
    });

      两秒后所有状态才变为resolved,然后输出结果。

    再看个例子:

    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(1);
        }, 2000);
    });
    const p2 = new Promise((resolve, reject) => {
        reject(2);
    });
    const p3 = new Promise((resolve, reject) => {
        reject(3);
    });
    
    Promise.all([p1, p2, p3]).then((data) => {
        console.log(data);
    }).catch((error) => {
        console.log(error) // 2
    });

    p2 状态变为rejected后,Promise.all()的状态就变为rejected,并打印出2,

    上文我们已经说过, promise的状态只会发生一次改变, 所以即使p3状态再变为rejected,

    Promise.all().catch也不会再输出了。

    ② Promise.race() 和 Promise.all()相反, 只要有一个状态变为resolved, 就会执行then的回调, 

    并且只打印第一个状态变化返回的值

    例子:

    const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(1);
        },3000);
    });
    const p2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(2);
        }, 1000)
    });
    const p3 = new Promise((resolve, reject) => {
        reject(3);
    });
    
    Promise.race([p1, p2, p3]).then((data) => {
        console.log(data + 'suc');
    }).catch((error) => {
        console.log(error + 'err'); // 3err
    });

    p3的状态最先发生改变所以打印3err.

    Promise.resolve( )  返回一个状态为resolved的promise对象

    Promise.reject() 返回一个状态为rejected 的promise对象

    注意事项,链式调用then()  如果不显示return, 隐式返回一个状态为resolved, 值为undefined的promise对象

    例子:

    const p3 = new Promise((resolve, reject) => {
        resolve(3);
    }).then((data) => {
        console.log(data)  // 3
        // return Promise.reject(2);
    }).then((data) => {
        console.log(data)   // undefined
    }).then((data) => {
        console.log(data)   // undefined
    });

    我们再显示return

    const p3 = new Promise((resolve, reject) => {
        resolve(3);
    }).then((data) => {
        console.log(data)  // 3
        return Promise.reject(2);
    }).then((data) => {
        console.log(data)   // 不输出
    }).then((data) => {
        console.log(data)   // 不输出
    }).catch((err) => {
        console.log('err' + err) // err2
    });

    catch也一样, 隐式返回一个状态为resolved, 值为undefined的promise对象,

    下一期我们来研究一下Promise的源码

     

  • 相关阅读:
    编写高质量代码 改善Python程序的91个建议 (读后 小记)
    Python itertools.combinations 和 itertools.permutations 等价代码实现
    图论期末大作业编程题(如何判断一个4连通4正则图为无爪、无K4图)
    2017年6月 六级成绩 有感(致逝去的研究生生活)
    Machine Learning 方向读博的一些重要期刊及会议 && 读博第一次组会时博导的交代
    个人经历北航计算机学院博士生申请审核制的所感
    转载: beta分布介绍
    目标检测之积分图---integral image 积分图2
    目标检测之harr---点角检测harr
    模式匹配之尺度空间---scale space
  • 原文地址:https://www.cnblogs.com/LHLVS/p/10645149.html
Copyright © 2011-2022 走看看