JS之Promise总结

  1. Promise 是异步编程的一种解决方案,主要解决异步操作多的时侯出现的问题:
    1. 异步处理结果顺序不定(如果对处理结果有次序要求的话);
    2. 为解决上面这个问题,那需嵌套异步处理而且要加判断是否成功,这样会导致代码结构复杂,难以维护;
  2. Promise的基本使用:
    1. 实例化 Promise时,要传入一个函数作为参数,通常写成箭头函数:()=>{}
    2. 这个参数又需2个参数,而且也是函数,一个是异步处理成功时调用,另一个是失败时调用,这2个参数通常用resolve和reject命名:(resolve,reject)=>{}这个就是Promise构造函数的参数,这2个函数参数由 JavaScript 引擎提供,不用自己部署,在Promise里直接调用就是,异步处理的结果作为其2个函数的参数;
    3. resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
    4. reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
  3. 然后里面写异步代码,比如ajax请求:(resolve,reject)=>{异步处理,比如ajax请求}
  4. then方法,Promise实例生成以后,再调用这个Promise实例的用then方法,then方法会等待Promise里的异步处理结果才会调用的,其可接受两个回调函数作为参数then(success=>{},error=>{})。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供,或者写到与then平级的catch方法里去处理异常。这两个函数都接受Promise对象传出的值作为参数。
  5. 以上总结有7个函数,用逗号分割描述:Promise构造函数,构造函数的参数也是个函数,resolve函数,reject函数,promise实例的then函数,then的成功函数,then的失败函数(可选)
  6. 又可以继续异步操作,不过是在then方法里的第1个函数里;
	// 简单应用,仔细看,有7个函数
      const p = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("ok123");  //这里传什么,then的第一个函数里就打印什么,这里是传异步结果出去的
          return; //加return,避免resolve(异步结构)后,还执行后面的代码
          console.log("...."); //不会执行
          //如果失败,需手动调用 reject()方法,参数可以自定义传出去,then的第2个函数会接收到
        }, 1000);
      });
      console.log("aaa"); // 1.先打印出来
      p.then(
        (result) => console.log(result), // 2.后打印出来
        (err) => console.log(err) //异常信息打印,这里没异常
      );
	// 打印结果
	aaa
	ok123
  1. then方法返回的是一个新的Promise实例,如果返回的是普通值(非Promise对象),then内部也会把结果封装到一个新的Promise对象,以便then后还可以调用then拿到这个普通值,实现链式调用,如果返回的就是Promise对象,那后面自然还可以用then链式调用;
  2. 多次的异步操作用Promise通常用法是:
    1. 创建一个函数;
    2. 在这个函数里先创建一个Promise对象并最终返回return这个Promise对象;
    3. 回头把异步处理写在这个Promise对象里;
    4. 最终呈现的是调用这个函数,返回一个Promise对象,接着再调用其then方法,这时处理了第1个异步操作且结果会在then里得到,在then里再调用这个创建的函数并return出去,这样又返回一个Promise,又可调用then方法,如此链式调用下去,再不考虑异常的情况下(then方法只有一个成功的处理函数作参数):
      //把异步操作(setTimeout)封装到一个Promise对象里,再用一个函数(getData)封装Promise对象,最后返回这个Promise对象
      function getData(url) {
        return new Promise((resolve, reject) => { //返回这个Promise对象
          // 模拟异步处理,实际可能是ajax请求
          setTimeout(() => {
            resolve("异步处理结果:" + url); // 把处理结果通过resovle传出去
          }, Math.ceil(Math.random() * 3) * 1000); //模拟异步操作,耗时在1-3秒内
        });
      }

//最终呈现的效果,3次异步请求按顺序调用并按顺序返回结果,而且代码结构清晰,每次then方法里发起一次异步请求
       getData("第1次请求数据")            //第1次异步请求数据
        .then((res) => {
          //拿到第1次异步处理后得到的数据
          console.log(res);
          return getData("第2次请求数据"); //第2次异步请求数据
        })
        .then((res) => {
          //拿到第2次异步处理后得到的数据
          console.log(res);
          return getData("第3次请求数据"); //第3次异步请求数据
        })
        .then((res) => {
        //拿到第3次异步处理后得到的数据
          console.log(res);
        });
		//按顺序逐步打印的结果:
		异步处理结果:第1次请求数据
		异步处理结果:第2次请求数据
		异步处理结果:第3次请求数据
  1. 通过打印console.dir(Promise);,发现then,catch,finally3个函数是在Promise的原型对象上,所以所有的Promise对象都可以调用这3个函数,而all,allSettled,race,reject,resolve是类方法(有的也称对象方法),只能通过Promise.调用,实例对象不可调用;
    1. Promise.all():并发处理多个任务,只有所有任务都完成才能得到结果;
      • 参数是个Promise对象数组,Promise.all([p1,p2,p3]).then(res => { }),返回结果res也是个数组,对应3个Promise对象的处理结果;
    2. Promise.race(): 并发处理多个任务,只要有一个任务都完成,就能得到结果;
      • 参数是个Promise对象数组,Promise.race([p1,p2,p3]).then(res => { }),返回结果res是3个Promise对象中,最快处理完的那个的结果;
原文地址:https://www.cnblogs.com/zoulei0718/p/14315560.html