首页 > 其他分享 >12——Promise

12——Promise

时间:2023-03-05 10:45:42浏览次数:41  
标签:12 const name resolve Promise reject console

第十二周

Promise

初识Promise
  • Promise

    • 异步操作的一种解决方案

      • 回调函数,异步操作的一种解决方案
    • 什么时候使用

      • 一般用来解决层层嵌套的回调函数,(回调地狱 callback hell)
    • const move = (el, {x=0, y=0} = {}, end = () => {}) => {
          el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
          el.addEventListener(
          	'transitionend',
          	() => {
                  end();
          	},
          	false
          );
      };
      const boxEl = document.getElementById('box');
      document.addEventListener(
      	'click',
      	() => {
              move(boxEl, {x:200}), () => {
                  move(boxEl, {x:200, y:200}, () => {
                      move(boxEl, {y:200}, () => {
                          move(boxEl);
                      });
                  });
              });
      	},
      	false
      );
      
    • 基本用法

      • 实例化对象

        • const p = new Promise((resolve, reject)=>{...});
          // 构造函数参数是回调函数,回调函数有两个回调函数参数
          
      • promise 状态

        • Promise 有三种状态,一开始是padding ,执行 resolve ,变成fulfilled (resolved)已成功,执行reject ,变成rejected 状态,已失败
        • 状态一旦完成变化,就不会再改变了
        • 成功状态的Promise 对象:value 属性和 status 属性
        • 失败状态的Promise 对象:reason 属性和 status 属性
      • then 方法

        • p.then(()=>{}, ()=>{});
          
        • 第一个回调函数成功时执行,第二个回调函数失败时执行

      • resolve 和 reject 函数的参数

        • 它们的参数被then 方法接收
Promise 实例方法
  • then()

    • 什么时候执行

      • padding -> fulfilled 时,执行 then 第一个回调函数
      • padding -> rejected 时,执行 then 第二个回调函数
    • 执行后的返回值

      • 返回新的Promise 对象
    • then 方法返回的Promise 对象的状态改变

      • const p = new Promise((resolve, reject)=>{
            resolve();
            // reject();
        });
        p.then(
        	() => {},
        	() => {
                // 在then 的回调函数中,return 后面的东西,会用 Promise 包装一下
                // return undefined;
                // 等价于:
            	return new Promise((resolve, reject) => {
                    resolve(undefined);
            	});
            	// 默认情况下调用 resolve 并且这里会把 undefined 传过来
            	// 默认返回的都是成功的状态
            	// 如果想返回失败的,就自己写就好了
            	return new Promise((resolve, reject) => {
                    reject('xxx');		// 传参给后面
        		});
        	}
        ).then(
        	() => {},
        	() => {}
        )
        
    • 向后传值(上面)

      • 成功的:直接return 失败的:自己写的 reject 函数调用时传的参数
    • 使用Promise 解决回调地狱

    • const move = (el, {x=0, y=0} = {}, end = () => {}) => {
          el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
          el.addEventListener(
          	'transitionend',
          	() => {
                  end();
          	},
          	false
          );
      };
      const movePromise = (el, point) => {
          return new Promise(resolve => {
              move(el, point, () => {
                  resolve();
              });
          });
      };
      const boxEl = document.getElementById('box');
      document.addEventListener(
      	'click',
      	() => {
              movePromise(boxEl, {x: 200}).then(() => {
                  return movePromise(boxEl, {x: 200, y: 200})
              }).then(() => {
                  return movePromise(boxEl, {y: 200})
              }).then(() => {
                  return movePromise(boxEl)
              });
      	},
      	false
      )
      
    • Promise 代码:横向发展,回调地狱:纵向发展

  • catch()

    • 作用:专门处理rejected 状态

    • 本质就是 then 的特例,then(null, err=>{})

    • new Promise((resolve, reject) => {
          reject('res');
      }).then(data => {
          console.log(data);
      })
      // .then(null, err => {
      //     console.log(err);
      // })
      .catch(err => {
          console.log(err);
          throw new Error('res');
      });
      // 第一个then 里面没有第二个回调,无法接收错误,这里并不会执行,同时,错误不会消失,会向下传导
      // 这里的catch 就相当于第二个then 的写法
      
    • 一般建议Promise 后面跟着catch ,而then 可以不写第二个回调

  • finally()

    • 什么时候执行
      • Promise 状态发生变化后,不论何种状态都会执行
    • 本质:特殊的 then
Promise 构造函数方法
  • Promise.resolve()

    • 成功状态的 Promise 简写

    • 参数:

    • // 111 一般参数
      new Promise(resolve => resolve('foo'));
      Promise.resolve('foo');
      
      
      // 222 Promise 对象作为参数
      const p1 = new Promise(resolve => {
          setTimeout(resolve, 1000, '执行了');
      });
      Promise.resolve(p1).then(data => {
          console.log(data);
      });
      // 实际上,当Promise.resolve() 接收的是 Promise 对象时,直接返回这个Promise 对象,什么都不做,状态改变到成功或者失败都不被影响,如果接收的是 Promise 对象,直接看里面就好了
      // 上面那行代码就相当于:
      p1.then(data => {
          console.log(data);
      });
      
      console.log(Promise.resolve(p1) === p1);			// true
      
      
      // 222 的衍生, Promise 对象,作为resolve 方法的参数时
      new Promise(resolve => resolve(p1)).then(data => {
          console.log(data);
      });
      // 注意,这里不会直接传Promise 对象,如果参数是Promise 对象,会执行,然后根据结果再传递参数,这里结果就是   “ 执行了 ” ;
      // 后面的 then 会根据传递的 Promise 变化后的状态 ,决定执行 then 中哪个回调函数
      
      
      // 333 具有then 方法的对象,首先会直接调用then 方法,再根据then 返回的Promise 状态决定执行和后面的 then 哪一个回调函数
            const obj = {
              then: (fun1, fun2) => {
                //   reject("res");
                fun1("xxx");
              },
            };
            Promise.resolve(obj).then(
              (data) => console.log(data),
              (err) => console.log(err)
            );
      
  • Promise.reject()

    • 和resolve 很类似

    • 参数:不管什么参数,直接原封不动向后传递

      •       const p2 = new Promise((resolve, reject) => resolve("123"));
          
              Promise.reject(p2).then(
                (data) => console.log("data " + data),
                (err) => console.log("err " + err)
              );
              
              // 结果:  err [object Promise]
        
      • 传递的就是 p 本身,且p 不执行不考虑状态,且直接执行 then 第二个回调

    • 上面两个方法区别:

      • // 不管 p 本身会成功还是失败
        console.log(Promise.resolve(p) === p);			// true
        console.log(Promise.reject(p) === p);			// false
        
      • 而 resolve 之后接的 then 会根据p 的状态来决定执行哪个,而reject 不考虑p 的状态,直接执行第二个回调,直接传递p 对象

      • resolve 传递状态,以及参数,reject 直接执行失败回调,传递p 对象

  • Promise.all()

    • 作用:关注多个 Promise 对象的状态变化,可以传递多个Promise 实例,包装成一个新的 Promise 对象实例返回

    •       const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
        
            const p1 = delay(1000).then(() => {
              console.log("p1");
              return "p1";
              // return Promise.reject("foo");
            });
            const p2 = delay(2000).then(() => {
              console.log("p2");
              return "p2";
            });
        
            const p = Promise.all([p1, p2]);
            p.then(
              (data) => console.log(data),
              (err) => console.log(err)
            );
      
    • 有点类似 && 运算,如果有一个失败了,会提前结束

  • Promise.race()

    • 作用: 与 all 类似, 也是管理多个Promise 状态
    • 状态取决于第一个完成的Promise 对象, 第一个成功则执行成功回调,第一个失败则执行失败回调,后面的Promise 还是会执行
    • 注意,这里说的第一个完成指的是快慢,而不是传递参数的顺序
  • Promise.allSettled()

    • 状态与传入的 Promise 对象的状态改变无关,永远执行成功回调,状态永远是成功的,只是记录一下各个Promise 的表现,成功的话,包括value 属性和status 属性,失败的话,包括reason 属性和status 属性,内部的返回值就是这样,也是返回用数组包装起来,每一个数据是对象
Promise 注意事项和应用
  • resolve 和 reject 执行后的代码

    • 会执行
  • Promise构造函数方法 all / race / allSettled 的参数问题

    • 参数数组中的元素,如果不是Promise 对象,会转成Promise 对象处理,下面等价

    • Promise.all([1, 2, 3]).then(datas => {	console.log(datas)	});
      Promise.all([
          Promise.resolve(1),
          Promise.resolve(2),
          Promise.resolve(3)
      ]).then(datas => {	console.log(datas)	});
      
    • 不只是数组,任何可遍历的数据都可以作为参数,包括原生可遍历和非原生可遍历

  • Promise构造函数方法 all / race / allSettled 的错误处理

    • all
      • 给每一个Promise 后面加catch,在allPromise 后面加整体的
  • 应用

class

初识
  • 定义形式——声明形式

    • class Person{
          constructor(name, age){
              this.name = name;
              this.age = age;
              
              // 一般公用的方法不放在这里,不然内存浪费
          }
          // 各个实例公用的方法
      }
      typeof Person 			// function
      
    • 本质上还是函数那一套,构造函数

  • 定义形式——表达式形式

    • const Person = class {
          constructor(name, age){
              this.name = name;
              this.age = age;
              
              // 一般公用的方法不放在这里,不然内存浪费
          }
          // 各个实例公用的方法
      }
      
    • 立即执行类

    • new (class {
          constructor(){
              ...
              // constructor 里面的内容会立即执行
          }
      })();
      
class 属性和方法
  • 实例属性(方法)

    • const Person = class {
      	sex = 'male';
      	// 实例属性,包括方法,所有实例都有的部分
          constructor(name, age){
              this.name = name;
              this.age = age;
          }
      };
      
  • 静态方法(类方法)

    • const Person = class {
      	sex = 'male';
          constructor(name, age){
              this.name = name;
              this.age = age;
          }
          
          // 重名也可以,不会弄混
          speak(){}
          static speak(){}
      };
      // 在外面也可以,建议写里面
      Person.speak(){};
      Person.speak();				// 类调用
      
  • 静态属性(类属性)

    • const Person = class {
      	sex = 'male';
          constructor(name, age){
              this.name = name;
              this.age = age;
          }
          
          // 不建议写里面,目前只是提案,有些浏览器不支持
          static version = 1.0
          
          // 建议把属性变成方法形式写,这样就没有兼容性问题了
          static getVersion(){
              return 1.0;
          }
      };
      // 在外面也可以,也不建议
      Person.version = 1.0
      Person.version;				// 类调用
      
  • 私有属性和方法

    • 为什么要有

      • 一般情况下,都是公开的,希望有一些不会被访问到
    • 模拟私有

      • 约定俗成:_开头的表示私有

      • 将私有属性和方法移出类

        • 模拟模块,其实也就是闭包的原理,利用闭包模拟私有属性

          • (function(){
            	let name = '';
            	// 这里就相当于闭包的变量了
                const Person = class {
                    sex = 'male';
                    constructor(username){
                        name = username;
                    };
                	getName(){
                        return name;
                	}
            	};
            	window.Person = Person;
            })();
            
            (function(){
                const p = new Person('alex', 1);
                p.getName();
            })();
            
        • 好处:实现了私有化,坏处:得借用外面变量,对类整体封装是一个破坏

class 继承
  • 子类继承父类

    • class Person{
          constructor(name, sex){
              this.name = name;
              this.sex = sex;
              
              this.say = function(){};
          }
          speak(){};
          static speak(){};
      }
      Person.version = 1.0;
      
      class Programmer extends Person{
          constructor(name, sex){
              super(name, sex);			// 这里super 就相当于父类的constructor
              // super 前面一定不能有this 的操作,有其他操作都没事
          }
      }
      // 所有东西都继承到了,子类同名覆盖
      
  • 改写继承属性/方法

    • super 作为函数调用
      • 只能在子类的构造方法中使用,相当于调用了父类的构造方法,在其他地方调用会报错
      • 这里注意一下,如果父类构造方法中有打印this,会直接看到打印出子类this,这是因为指向的是执行者,也就是子类执行的,指向子类实例
    • super 作为对象使用
      • 在哪里使用没有限制了,代表的是 父类的.prototype ,注意哪些在原型上,哪些不在,父类的构造方法上的 this 上的东西都不在,是专属实例的
      • 通过 super 调用父类方法时,方法内部的 this 指向当前子类实例
      • 在静态方法中使用,super 指向父类而不是 父类.prototype , this 同样指向子类,但不是子类的实例了
    • 注意事项
      • 使用时必须显示出作为函数还是对象使用,不然浏览器也不知道,会直接报错
class 应用

标签:12,const,name,resolve,Promise,reject,console
From: https://www.cnblogs.com/autowe/p/17179987.html

相关文章