使用 Promise 处理异步编程入门

2022-01-21 0 By admin

一、Promise 异步方式介绍

1.1、什么是Promise?

Promise 是在 js 中进行异步编程的新解决方案。

  1. 从语法来说,promise是一个构造函数。
  2. 从功能来说,promise对象用来封装一个异步操作,并且可以获得成功或失败的返回值。

JS中的常见的异步操作:定时器,AJAX请求等是异步操作(也可以同步),回调函数可以理解为异步(不是严谨的异步操作)…等。

1.2、为啥使用Promise?

promise 使用回调函数更灵活。

  1. 执行过程:启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至能在异步任务结束后指定多个)。
  2. 支持链式调用,可以解决回调地狱问题。(回调地狱就是多层回调函数嵌套使用,就是套娃,这样就不利于阅读和异常处理。)

二、promise 入门示例

效果:点击一个按钮,有30%概率显示中奖。
实现: 点击按钮后得到一个1到100间的随机数,小于等于30输出中奖,否则输出没中。期间用定时器模拟异步操作,在定时器里执行判断。

2.1、基础的写法

<button id="btn">click</button>
<script>
    var btn = document.querySelector("#btn");
// 该函数返回一个两数之间的随机整数,包括两个数在内
function getRandomIntInclusive(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
}
// 点击事件
 btn.addEventListener('click',function(){
     // 1秒的定时器,模拟异步操作
     setTimeout(() => {
         // 得到1到100间的一个数
         let n = getRandomIntInclusive(1, 100);
         if (n <= 30) {
             alert('中奖喽');
         } else {
             alert('没中奖');
         }
     }, 1000);
 })
</script>

2.2、Promise 的写法

在promise里封装一个异步操作。

<script>
    var btn = document.querySelector("#btn");
// 点击事件
 btn.addEventListener('click',function(){
// 下面是promise ,resolve表示解决,reject表示拒绝 ,都是函数类型数据。
     const p = new Promise((resolve,reject) => {
         setTimeout(()=>{
              let n = getRandomIntInclusive(1, 100);
              if(n<=30){
                  resolve(); //将promise状态设为 “成功”
              }else{
                  reject(); //将promise状态设为 “失败”
              }
         },1000)
     });
// 调用then方法
     p.then(()=>{
         // “成功”执行这步
        alert('中奖喽');
     },()=>{
         // “失败”执行这步
        alert('没中奖');
     })
 })

2.3、Promise 传输执行结果

假如要在上面输出结果后加上选中的号码;
因为.then() 里并不能直接获得 n,所以在 resolve 与 reject 里把n当结果值返回。

btn.addEventListener('click',function(){
// 下面是promise ,resolve表示解决,reject表示拒绝 ,都是函数类型数据。
    const p = new Promise((resolve,reject) => {
        setTimeout(()=>{
             let n = getRandomIntInclusive(1, 100);
             if(n<=30){
                 resolve(n); //将promise状态设为 “成功”,并把结果值n返回
             }else{
                 reject(n); //将promise状态设为 “失败”,并把结果值n返回
             }
        },1000)
    });
// 调用then方法; value为值的意思,reason为理由的意思,都是形参
    p.then((value)=>{
        // “成功”执行
       alert('中奖喽'+value);
    },(reason)=>{
        // “失败”执行
       alert('没中奖'+reason);
    })
})

三、promise 封装 ajax请求示例

3.1、基本Ajax 请求示例

<script>
var btn = document.querySelector("#btn");
// 点击事件
btn.addEventListener('click',function(){
   //创建对象
   const xhr = new XMLHttpRequest();
   //初始化
   xhr.open('GET',"http://poetry.apiopen.top/sentences");
   //发送
   xhr.send();
   //处理响应结果
   xhr.onreadystatechange = function(){
       if(xhr.readyState === 4){
           if(xhr.status >=200 && xhr.status < 300){
               //输出响应体
               console.log(xhr.response);
           }else{
               //输出响应状态码
               console.log(xhr.status);
           }
       }
   }
 })
</script>

3.2、promise 包装 Ajax 请求

btn.addEventListener('click',function(){
const p = new Promise((resolve,reject) => {
     //创建对象
	const xhr = new XMLHttpRequest();
    //初始化
    xhr.open('GET', "http://poetry.apiopen.top/sentences");
    //发送
    xhr.send();
    //处理响应结果
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            if (xhr.status >= 200 && xhr.status < 300) {
                //输出响应体
               resolve(xhr.response);
            } else {
                //输出响应状态码
                reject(xhr.status);
            }
        }
    }
})
	
// 调用then方法;
p.then(value=>{
     console.log(value);
   },reason=>{
    //控制台输出警告信息
      console.warn(reason);
   })
})

3.3、Promise封装ajax请求

跟上一步差不多。就是把其封装在一个sendAJAX()的自定义函数里。

// 定义封装函数
function sendAJAX(url) {
  return new Promise((resolve, reject) => {
     //创建对象
     const xhr = new XMLHttpRequest();
     xhr.responseType = 'json';
     //初始化
     xhr.open('GET', url);
     //发送
     xhr.send();
     //处理响应结果
     xhr.onreadystatechange = function () {
       if (xhr.readyState === 4) {
           if (xhr.status >= 200 && xhr.status < 300) {
               //输出响应体
               resolve(xhr.response);
           } else {
               //输出响应状态码
               reject(xhr.status);
           }
       }
     }
     });
}
//调用
sendAJAX("http://poetry.apiopen.top/sentences")
.then(value=>{
         console.log(value);
    },reason=>{
        //控制台输出警告信息
          console.warn(reason);
    })