JavaScript的执行机制(async/await)(二)

写在最前面

问题1?

项目中经常会遇到通过请求获取某个值或者条件后,根据值或者条件去执行其他操作的情况,但往往请求属于异步任务,导致没拿到值或者条件时,就执行了之后的操作,会因为值为空或者条件不满足而导致报错!只能将后续代码写在请求promist.then()中,导致代码不可维护,不灵活,所谓的‘函数瀑布’。

理想状态下:

     console.log('执行上一步操作')
     alert('请求接口满足了条件')
     console.log('根据条件执行下一步操作')

打印结果如下

1.执行上一步操作

2.弹出‘请求接口满足了条件’,点击确定

3.根据条件执行下一步操作

 现实状态下:

      console.log("执行上一步操作");
      var sino = null;
      new Promise((resolve) => {
        setTimeout(() => {
          sino = "满足";
          resolve(sino);
        }, 3000);
      }).then(() => {
        console.log(`条件${sino}`);
      });
      console.log(`根据条件${sino}执行下一步操作`);

打印结果如下

1.执行上一步操作

2.根据条件null执行下一步操作(后续代码会拿不到条件)

3.等待3秒后打印 条件满足

通常的解决办法:

      console.log("执行上一步操作");
      var sino = null;
      new Promise((resolve) => {
        setTimeout(() => {
          sino = "满足";
          resolve(sino);
        }, 3000);
      }).then(() => {
        console.log(`条件${sino}`);
        console.log(`根据条件${sino}执行下一步操作`);
      });

 打印结果如下:

1.执行上一步操作
2.等待3秒后 条件满足
3.根据条件满足执行下一步操作


 有没有更好的解决办法?

1.async-await异步请求同步化

2.await后面接一个 new promise函数或者会return new promist的函数并执行它

3.await只能放在async函数里

 上代码:

    async fn() {
      console.log("执行上一步操作");
      var sino = null;
      sino = await new Promise((resolve) => {
        setTimeout(() => {
          sino = "满足";
          console.log(`${sino}`);
          resolve(sino);
        }, 3000);
      });
      console.log(`根据条件${sino}执行下一步操作`);
    },
    fn()

打印结果如下:

1.执行上一步操作

2.满足

3.根据条件 满足 执行下一步操作

 封装后:

    fetchSino() {
      return new Promise((resolve) => {
        setTimeout(() => {
          let sino = "满足";
          console.log(sino);
          resolve(sino);
        }, 3000);
      });
    },
    async fn() {
      console.log("执行上一步操作");
      const sino = await this.fetchSino();
      console.log(`根据条件${sino}执行下一步操作`);
    },
    fn()

1.执行上一步操作

2.满足

3.根据条件 满足 执行下一步操作

 此处需要注意:

扩展 :await 等到之后,做了一件什么事情?

问题1:如果await后面不是promise对象呢

    fetchSino() {
      let sino = "满足";
      console.log(sino);
      return sino;
    },
    async fn() {
      console.log("执行1");
      const sino = await this.fetchSino();
      console.log(`根据条件${sino}执行下一步操作`);
    },
    fn()
    console.log('执行fn后操作')
    // 执行1
    // 满足
    // 执行fn后操作
    // 根据条件满足执行下一步操作

fn()执行,进入函数内部,遇到await ,去执行后面的函数 ,如果发现该函数不是return new Promist的函数, await都会执行完,让出线程,阻塞后面的代码继续执行,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果。

问题2:如果请求失败或者没有return结果呢?

请求失败: 

    fetchSino() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let sino = "不满足";
          console.log(sino);
          reject(sino);
        }, 3000);
      });
    },
    async fn() {
      console.log("执行上一步操作");
      const sino = await this.fetchSino();
      console.log(`根据条件${sino}执行下一步操作`);
    },
    fn()
    // 执行上一步操作
    // 不满足
    // Uncaught (in promise) 不满足
    // 后面就没有打印任何东西

没有return结果:

    fetchSino() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let sino = "不满足";
          console.log(sino);
        }, 3000);
      });
    },
    async fn() {
      console.log("执行上一步操作");
      const sino = await this.fetchSino();
      console.log(`根据条件${sino}执行下一步操作`);
    },
    fn()
    // 执行上一步操作
    // 不满足
    // 后面就没有打印任何东西

await右侧表达式的结果,就是await要等的结果,结果成功返回,继续执行下面的代码,如果没有返回结果或者promise返回失败,对于await来说就是失败了,则会让出线程,阻塞代码,因此在项目中需要运用try catch解决

    fetchSino() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let sino = "不满足";
          reject(sino);
        }, 3000);
      });
    },
    async fn() {
      try {
        console.log("执行fetchSino");
        const sino = await this.fetchSino();
        console.log(`根据条件${sino}执行下一步操作`);
      } catch (error) {
        console.log(error);
        console.log(`根据条件不满足操作`);
      }
    },
    fn()

    // 执行fetchSino
    // 不满足(catch打印)
    // 根据条件不满足操作(catch打印)

 问题3:在axios中如何运用async/await异步请求同步化?

Axios 是一个基于 promise 的 HTTP 库,axios返回的就是一个Promise对象

 不多bb,上代码:

    async fn() {
      try {
        let result = await axios.get('/api/survey/list/')
        result && console.log('执行请求后的操作')
      } catch (err) {
        console.log(err)
      }
    },
    fn()

写在最后 

我们都拥有足够的时间,只是要善加利用。一个人如果不能有效利用有限的时间,就会被时间俘虏,成为时间的奴隶。一旦在时间面前成为弱者,他将永远是一个弱者。因为放弃时间的人,同样也会被时间放弃。

                                                                                                                                  ——歌德

下一篇:大名鼎鼎的Promise,看完此篇,从此不再谈之色变


版权声明:本文为weixin_44959855原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。