ES6中的基础知识点 — Promise

1、Promise的简单介绍和基本使用

Promise是异步编程的一种解决方案

why需要引入Promise
在开发项目的过程中,我们可能需要发送网络请求,由于网络请求是一个异步事件,不能立即拿到结果,所以我们会封装一个网络请求函数,并传入一个回调函数,当数据请求成功时,将数据通过传入的函数回调出去。这种方案虽然也能拿到我们想要的数据,但是一旦网络请求非常复杂时,就会出现回调地狱,导致代码的可读性很差。而使用promise就能很好的解决地狱回调的问题。

这里使用简单的例子来说明:
以setTimeout来模拟异步请求,如果不使用promise,则

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的基本使用</title>
</head>
<body>

<script>
  // 1.发送第一次请求
  setTimeout(() => {
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');

    // 2.发送第二次请求
    setTimeout(() => {
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');

      // 3.发送第三次请求
      setTimeout(() => {
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
      }, 3000)
    }, 2000)
  }, 1000)
</script>

</body>
</html>

显示效果:

在这里插入图片描述

在使用过程中,我们发现,代码嵌套真的是太严重了,如果有多个请求,那么代码的可读性是很差的,so,我们可以使用promise来进行异步请求的处理

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的基本使用</title>
</head>
<body>

<script>
  new Promise((resolve, reject) => {
    // 1.发送第一次请求
    setTimeout(() => {
      resolve();
    }, 1000)
  }).then(() => {
    // 处理第一次请求
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');
    console.log('first, 我是第一次请求!!!');

    // 2.发送第二次请求
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 2000)
    }).then(() => {
      // 处理第二次请求
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');
      console.log('second, 我是第二次请求!!!');

      // 3.发送第三次请求
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve();
        }, 3000)
      }).then(() => {
        // 处理第三次请求
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
        console.log('third, 我是第三次请求!!!');
      })
    })
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

简单介绍一下Promise
在执行Promise时,会传入两个参数:resolve, reject。而它们本身又是函数
Promise是一种链式编程,下面以一个例子展示Promise的使用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的基本使用</title>
</head>
<body>

<script>
  new Promise((resolve, reject) => {
    // 模拟发送网络请求
    setTimeout(() => {
      // 1.请求成功时调用 resolve()
      resolve('hello, success. YiBo');

      // // 2.请求失败时调用 reject()
      // reject('err, you are wrong')
    }, 1000)
  }).then((data) => {
    // 获取到resolve中传入的数据
    console.log(data);
  }).catch((err) => {
    // 获取到reject中的数据
    console.log(err);
  })

</script>

</body>
</html>

显示效果:

在这里插入图片描述

请求失败时的代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的基本使用</title>
</head>
<body>

<script>
  new Promise((resolve, reject) => {
    // 模拟发送网络请求
    setTimeout(() => {
      // 1.请求成功时调用 resolve()
      // resolve('hello, success. YiBo');

      // 2.请求失败时调用 reject()
      reject('err, you are wrong')
    }, 1000)
  }).then((data) => {
    // 获取到resolve中传入的数据
    console.log(data);
  }).catch((err) => {
    // 获取到reject中的数据
    console.log(err);
  })

</script>

</body>
</html>

显示效果:

在这里插入图片描述

2、Promise的三种状态

Promise有三种状态:

  • pending:等待状态。eg:比如正在进行网络请求,或者定时器没有到时间
  • fulfilled:当调用resolve(),成功,状态会由 pending 转换为 fulfilled 状态
  • rejected:当调用reject(),失败,状态会由 pending 转换为 rejected 状态

3、Promise的另外处理方式

在Promise的.then()中,也可以处理请求失败的数据信息。下面以例子进行简单的介绍。

请求成功:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的另外请求方式</title>
</head>
<body>

<script>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('hello, YiBo!!!');
      // reject('oh my god, you missed me');
    })
  }).then((res) => {
    console.log(res);
  }, (err) => {
    console.log(err);
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

请求失败:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise的另外请求方式</title>
</head>
<body>

<script>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      // resolve('hello, YiBo!!!');
      reject('oh my god, you missed me');
    })
  }).then((res) => {
    console.log(res);
  }, (err) => {
    console.log(err);
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

4、Promise的链式调用

这里以一个例子展示Promise的链式调用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)
  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return new Promise((resolve, reject) => {
      resolve(res + '111');
    })
  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    return new Promise((resolve, reject) => {
      resolve(res + '222');
    })
  }).then((res) => {
    console.log(res, '第三层处理10行代码');
  })
</script>

</body>
</html>

在这个例子中,我们发现,每次数据的拼接都新 new了一个 Promise对象,但是在这个过程中,我们并没有异步请求。对于这种情况,我们可以不使用 new Promise来进行处理,可以直接使用 Promise.resolve() 来进行数据的处理。

代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)
  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return Promise.resolve(res + '111');

  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    return Promise.resolve(res + '222');

  }).then((res) => {
    console.log(res, '第三层处理10行代码');
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

虽然使用 Promise.resolve() 来进行数据拼接的操作已经比较简洁了,但是我们也可以直接return 来进行数据拼接操作。在进行return操作时,其实promise内部会帮我们进行一些包装,实际上也是以Promise.resolve的形式进行数据的拼接操作。
代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)
  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return res + '111';

  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    return res + '222';

  }).then((res) => {
    console.log(res, '第三层处理10行代码');
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

当我们发送数据失败时,会进入.catch() 处理后续的信息
代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)

  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return new Promise((resolve, reject) => {
      resolve(res + '111');
    })

  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    return new Promise((resolve, reject) => {
      // resolve(res + '222');
      reject('err!!! you are wrong!!!')
    })

  }).then((res) => {
    console.log(res, '第三层处理10行代码');

  }).catch((err) => {
    console.log(err);
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

由于在这里也没有使用异步操作,所以也可以不用 new 一个Promise,可以使用***Promise.reject()***实现 reject()的操作。
代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)

  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return Promise.resolve(res + '111');

  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    return Promise.reject('err!!! you are wrong!!!');

  }).then((res) => {
    console.log(res, '第三层处理10行代码');

  }).catch((err) => {
    console.log(err);
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

除了使用 promise.reject(),也可以使用 throw来抛出错误信息
代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise链式调用</title>
</head>
<body>

<script>
  /*
  业务需求:发送网络请求,传输数据: one, 自己进行处理
  处理完成后,在数据后面拼接:111, 然后自己处理数据
  处理完成后,在数据后边拼接:222, 然后自己处理数据
   */

  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('one');
    }, 1000)

  }).then((res) => {
    console.log(res, '第一层处理10行代码');
    return Promise.resolve(res + '111');

  }).then((res) => {
    console.log(res, '第二层处理10行代码');
    throw('err!!! you are wrong!!!');

  }).then((res) => {
    console.log(res, '第三层处理10行代码');

  }).catch((err) => {
    console.log(err);
  })
</script>

</body>
</html>

显示效果:

在这里插入图片描述

5、Promise中all方法的使用

all方法需要使用的场景:
在实际项目开发过程中,我们可能需要同时接受多个请求,接受了多个请求之后才能够对数据进行处理,这个时候,我们可以使用Promise中的all方法同时获取多个请求的数据。

Promise.all([])      //all中传递的是一个可迭代对象

代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Promise中all方法的使用</title>
</head>
<body>

<script>
  Promise.all([
      new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({name: 'YiBo', age: 18});
        }, 2000)
      }),
      
      new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({name: '哈尔', age: 18});
        }, 1000)
      })

  ]).then(results => {
    console.log(results[0]);
    console.log(results[1]);
  })

</script>

</body>
</html>

显示效果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值