ES6-Promise下

六。实例的finally方法:

promise状态发生变化指的是由初始态变成成功或者失败态

处理错误指的是没有调用catch(失败态实例调用可以执行其回调的then)

finally里面的回调函数只要promise状态发生变化就会执行,但是接收不到参数

这里没有调用then方法,也会报错吗?什么时候报错?

应用场景:处理最终状态,比如js操作数据库,涉及异步操作,可以用promise,最终需要关闭数据库不论成功或者失败

finally的本质:

        new Promise(function (resolve, reject) {
            // resolve(1);
            reject('reason');
        }).finally(function () {
            console.log(1);
        });
        // 相当于下面
        new Promise(function (resolve, reject) {
            // resolve(1);
            reject('reason');
        })
            .then(
                result => {
                    console.log(1);

                    return result;
                },
                err => {
                    console.log(1);

                    return new Promise(function (resolve, reject) {
                        reject(err);
                    });
                }
            );

finally源码

      // 1.什么时候finally里面的回调执行
      // 当 Promise 状态发生变化时,不论如何变化都会执行,不变化不执行
      // new Promise((resolve, reject) => {
      //   // resolve(123);
      //   reject('reason');
      // })
      //   .finally(data => {
      //     console.log(data);
      //   })
      //   .catch(err => {});

      // 2.本质
      // finally() 本质上是 then() 的特例

      // new Promise((resolve, reject) => {
      //   // resolve(123);
      //   reject('reason');
      // })
      //   .finally(data => {
      //     console.log(data);
      //   })
      //   .catch(err => {});
      // 等同于
      new Promise((resolve, reject) => {
        // resolve(123);
        reject('reason');
      })
        .then(
          result => {
            return result;
          },
          err => {
            return new Promise((resolve, reject) => {
              reject(err);
            });
          }
        )
        .then(data => {
          console.log(data);
        })
        .catch(err => {
          console.log(err);
        });

七。构造函数Promise的方法

1.Promise.resolve()和Promise.reject()

注意,也不一定Promise.resolve()返回的就是成功状态p,看下面传有then方法的一般对象;

所以data接收的参数是p1实例里resolve的参数,也就是由p1接手了;

疑问:(前面已经解答)

 

解释为什么有这两个函数

同步异步定时器问题,去掉return问题前面的,为什么有的等1秒,有的不等

注意,挂起的then里面的回调会等当前的正在主车道执行的代码执行完再执行;

源码

    <script>
      // 1.Promise.resolve()
      // 是成功状态 Promise 的一种简写形式
      // new Promise(resolve => resolve('foo'));
      // // 简写
      // Promise.resolve('foo');

      // 参数
      // 一般参数
      // Promise.resolve('foo').then(data => {
      //   console.log(data);
      // });

      // Promise
      // 当 Promise.resolve() 接收的是 Promise 对象时,直接返回这个 Promise 对象,什么都不做
      // const p1 = new Promise(resolve => {
      //   setTimeout(resolve, 1000, '我执行了');
      //   // setTimeout(() => {
      //   //   resolve('我执行了');
      //   // }, 1000);
      // });
      // Promise.resolve(p1).then(data => {
      //   console.log(data);
      // });
      // 等价于
      // p1.then(data => {
      //   console.log(data);
      // });
      // console.log(Promise.resolve(p1) === p1);

      // 当 resolve 函数接收的是 Promise 对象时,后面的 then 会根据传递的 Promise 对象的状态变化决定执行哪一个回调
      // new Promise(resolve => resolve(p1)).then(data => {
      //   console.log(data);
      // });

      // 具有 then 方法的对象
      // function func(obj) {
      //   obj.then(1, 2);
      // }
      // func({
      //   then(resolve, reject) {
      //     console.log(a, b);
      //   }
      // });

      // const thenable = {
      //   then(resolve, reject) {
      //     console.log('then');
      //     resolve('data');
      //     // reject('reason');
      //   }
      // };
      // Promise.resolve(thenable).then(
      //   data => console.log(data),
      //   err => console.log(err)
      // );
      // console.log(Promise.resolve(thenable));

      // 2.Promise.reject()
      // 失败状态 Promise 的一种简写形式
      // new Promise((resolve, reject) => {
      //   reject('reason');
      // });
      // 等价于
      // Promise.reject('reason');

      // 参数
      // 不管什么参数,都会原封不动地向后传递,作为后续方法的参数
      // const p1 = new Promise(resolve => {
      //   setTimeout(resolve, 1000, '我执行了');
      // });
      // Promise.reject(p1).catch(err => console.log(err));

      new Promise((resolve, rejcet) => {
        resolve(123);
      })
        .then(data => {
          // return data;
          // return Promise.resolve(data);

          return Promise.reject('reason');
        })
        .then(data => {
          console.log(data);
        })
        .catch(err => console.log(err));
    </script>

2.Promise.all()方法

注意,参数里面有rejected实例的情况,只要根据代码执行顺序识别到有一个rejected实例,那么下图的p就变成失败态且接收识别到的失败态reject里面的参数a

等价于const p = Promise.reject(a),p和识别的那个rejected实例不是一个实例,只是参数和状态一样;

还有p由p1p2决定,p1p2赋值还未完成,所以p的赋值也未完成,同步执行时,定时器还没执行,delay函数return出去的也是暂时的,所以pp1p2也是暂时的pending状态,异步执行完毕,return后面的值刷新,delay(1000)delay(2000)的返回值也刷新,pp1p2的赋值也刷新;

如果all里面参数若为空数组的话,默认返回实例状态为成功

  <script>
    // 1.有什么用
    // Promise.all() 关注多个 Promise 对象的状态变化
    // 传入多个 Promise 实例,包装成一个新的 Promise 实例返回

    // 2.基本用法
    const delay = ms => {
      return new Promise(resolve => {
        setTimeout(resolve, ms);
      });
    };

    const p1 = delay(1000).then(() => {
      console.log('p1 完成了');

      // return 'p1';
      return Promise.reject('reason');
    });
    const p2 = delay(2000).then(() => {
      console.log('p2 完成了');

      return 'p2';
      // return Promise.reject('reason');
    });

    // Promise.all() 的状态变化与所有传入的 Promise 实例对象状态有关
    // 所有状态都变成 resolved,最终的状态才会变成 resolved
    // 只要有一个变成 rejected,最终的状态就变成 rejected

    const p = Promise.all([p1, p2]);
    p.then(
      data => {
        console.log(data);
      },
      err => {
        console.log(err);
      }
    );
  </script>
3.Promise.race() 和 Promise.allSettled()
取决于第一个,并不是全等第一个只是状态和参数一样;
关于异步程序执行顺序还有很多不懂(异步没写完)
    <script>
      const delay = ms => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      };
      const p1 = delay(1000).then(() => {
        console.log('p1 完成了');

        return 'p1';
        // return Promise.reject('reason');
      });
      const p2 = delay(2000).then(() => {
        console.log('p2 完成了');

        // return 'p2';
        return Promise.reject('reason');
      });

      // 1.Promise.race()
      // Promise.race() 的状态取决于第一个完成的 Promise 实例对象,如果第一个完成的成功了,那最终的就成功;如果第一个完成的失败了,那最终的就失败
      // const racePromise = Promise.race([p1, p2]);
      // racePromise.then(
      //   data => {
      //     console.log(data);
      //   },
      //   err => {
      //     console.log(err);
      //   }
      // );

      // 2.Promise.allSettled()
      // Promise.allSettled() 的状态与传入的Promise 状态无关
      // 永远都是成功的
      // 它只会忠实的记录下各个 Promise 的表现
      const allSettledPromise = Promise.allSettled([p1, p2]);
      allSettledPromise.then(data => {
        console.log('succ', data);
      });
    </script>
 
4.Promise.any()
 
八。Promise注意事项
    <script>
      // 1.resolve 或 reject 函数执行后的代码
      // 推荐在调用 resolve 或 reject 函数的时候加上 return,不再执行它们后面的代码
      // new Promise((resolve, reject) => {
      //   // return resolve(123);
      //   return reject('reason');

      //   console.log('hi');
      // });

      // 2.Promise.all/race/allSettled 的参数问题
      // 参数如果不是 Promise 数组,会将不是 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);
      // });

      // 不只是数组,任何可遍历的都可以作为参数
      // 数组、字符串、Set、Map、NodeList、arguments
      // Promise.all(new Set([1, 2, 3])).then(datas => {
      //   console.log(datas);
      // });

      // 3.Promise.all/race/allSettled 的错误处理
      const delay = ms => {
        return new Promise(resolve => {
          setTimeout(resolve, ms);
        });
      };

      const p1 = delay(1000).then(() => {
        console.log('p1 完成了');

        // return 'p1';
        return Promise.reject('reason');
      });
      // .catch(err => {
      //   console.log('p1', err);
      // });
      const p2 = delay(2000).then(() => {
        console.log('p2 完成了');

        return 'p2';
        // return Promise.reject('reason');
      });
      // // .catch(err => {
      // //   console.log('p2', err);
      // });

      const allPromise = Promise.all([p1, p2]);
      allPromise
        .then(datas => {
          console.log(datas);
        })
        .catch(err => console.log(err));

      // 错误既可以单独处理,也可以统一处理
      // 一旦被处理,就不会在其他地方再处理一遍
    </script>

九。promise应用

异步加载图片,停留在当前图片时,趁这个时间浏览器从服务器端加载其他资源,图片,然后点击切换按钮想要切换图片时,就可以显示到页面(通过dom),并不是点击切换才去服务器端加载这个图片

promise里的回调一般不写逻辑,一般写的是什么时候调用resolve或者reject;

如果不用promise的话,就会加两个形参接收回调函数,一个负责图片加载成功该怎么办,一个负责图片加载失败

注意img这里是个对象,是Image构造出来的实例,和dom对象没关系

注意这里的SRC属性是实例img的属性和html dom元素的SRC属性不一样

const img = new Image()只是实例化创建了一个img标签,也可以通过appendchild加入到html结构里

注意img.src=url,src属性值变化就能触发onload和onerror事件,img.src=url这个代码的作用就是一个工具,作用是像服务端发请求拿资源,这就是异步加载图片;

如果传进来的url并没有请求到图片,就会触发error事件

实际开发过程中,可能是点击按钮才切换图片;

如果图片加载失败(url错误)会有这个提示:

    <style>
      #img {
        width: 80%;
        padding: 10%;
      }
    </style>
  </head>
  <body>
    <img
      src="https://img.mukewang.com/5e6af63d00011da318720764.jpg"
      alt=""
      id="img"
    />

    <script>
      // 异步加载图片
      const loadImgAsync = url => {
        return new Promise((resolve, reject) => {
          const img = new Image();

          img.onload = () => {
            resolve(img);
          };

          img.onerror = () => {
            reject(new Error(`Could not load image at ${url}`));
          };

          img.src = url;
        });
      };

      const imgDOM = document.getElementById('img');
      loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')
        .then(img => {
          console.log(img.src);
          setTimeout(() => {
            imgDOM.src = img.src;
          }, 1000);
        })
        .catch(err => {
          console.log(err);
        });
    </script>

①代码执行loadImgAsync('https://2img.mukewang.com/5f057a6a0001f4f918720764.jpg')时,就会创建img对象,并给img对象赋予具体的src地址:

②此时就会开启网络请求,去网络中某一个具体的位置请求图片,即异步加载图片。图片加载完,就会继续执行如下:

由于图片所在的服务器响应特别快,并且我们的网络特别给力、电脑性能也特别好,因此加载图片这个异步过程会迅速完成,看上去和使用本地图片一样快。但是假设图片所在的服务器响应很慢,那么图片就会很慢的请求回来,举个常见的现象:某些网站,打开后,图片迟迟不展示,此时速度上,就有差异了。

 

十。如何统一处理错误?Promise参与过程中什么时候会报错?Promise.all等方法返回值是新的promise实例,和传进来的无关;

1.如何统一处理错误:

------------------------------------------------------------------------------------------------------------------------------------------------------

十一。async和await  (使得异步操作变得更加方便。)

async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

调用async函数时,会立即返回一个Promise对象。

注意await后面放的是一个可以求值的东西(函数调用等)

等待Promise返回结果:  ,如果跟的是promise实例这种情况,会等Promise实例过程中的所有代码全部执行完毕(不论同步异步)如果最终状态为成功态,执行该函数体后面的代码(打印end)

如果最终是失败态实例,该函数体后面的代码(打印end)不会执行且会报错;如果最终是pending状态,该函数体后面的代码(打印end)也不会执行

 

posted @ 2023-01-25 13:11  游千山  阅读(24)  评论(0)    收藏  举报