b站视频-尚硅谷Web前端Promise从入门到精通-笔记

目录

前言

在继续学习React-ajax、axios之前,先来学习promise
看的是b站尚硅谷李强老师的视频:Promise从入门到自定义

一、Promise视频简介

包含以下内容:

  1. Promise介绍与基本使用
  2. Promise API
  3. Promise关键问题
  4. Promise自定义封装
  5. async与await

二、Promise的介绍

ES6引入的进行异步编程的解决方案,从语法上说它是一个构造函数。
异步编程包括但不限于:文件操作、数据库操作、AJAX、定时器

为什么要用Promise?
支持链式调用,可以解决回调地狱问题,如下图,回调地狱不便于阅读和异常处理。
回调地狱

三、Promise的初体验

实现:
点击按钮, 1s 后显示是否中奖(30%概率中奖)
若中奖弹出 恭喜您中奖
若未中奖弹出 谢谢参与

//  Promise是构造函数,所以可以进行对象的实例化
// resolve和reject都是函数类型的数据
const p=new Promise((resolve,reject)=>{
    
    
    setTimeout(()=>{
    
    
    // 30%  1 2 ... 30
    // 获取从1-100的一个随机数
    let n=rand(1,100)
    // 判断
    if(n<=30){
    
    
        resolve(n); // 将 promise 对象的状态设置为 『成功』
    }else{
    
    
        reject(n); // 将 promise 对象的状态设置为 『失败』
    }
    },1000);
});

// 调用then方法
// 成功就调用第一个回调函数,失败调用第二个回调
p.then((value)=>{
    
    
    alert('恭喜您中奖,您的中奖号码为'+value);
},(reason)=>{
    
    
    alert('谢谢参与,您的号码为'+reason);
});

四、Promise实践练习

1. fs读取文件

let p=new Promise((resolve, reject)=>{
    
    
    fs.readFile('./resource/content.txt',(err,data)=>{
    
    
        // 如果出错 
        if(err) reject(err);
        // 如果成功
        resolve(data);
    });
});

p.then(value=>{
    
    
    console.log(value.toString());
},reason=>{
    
    
    console.log(reason);
})

在这里插入图片描述

2. AJAX请求

<script type="text/javascript">
        //接口地址 https://api.apiopen.top/getJoke
        //获取元素对象
        const btn = document.querySelector('#btn');

        btn.addEventListener('click',function(){
    
    
            // 创建Promise对象
            const p=new Promise((resolve,reject)=>{
    
    
                // 1.创建对象
                const xhr=new XMLHttpRequest();
                // 2.初始化
                xhr.open('GET','https://api.apiopen.top/getJoke');
                // 3.发送
                xhr.send();
                // 4.处理响应结果
                xhr.onreadystatechange=function(){
    
    
                    if(xhr.readyState===4){
    
    
                        // 判断响应状态码 
                        if(xhr.status>=200&&xhr.status<300){
    
    
                            // 控制台输出响应体
                            // console.log(xhr.response);
                            resolve(xhr.response);
                        }else{
    
    
                            // 控制台输出响应体
                            // console.log(xhr.status);
                            reject(xhr.status);
                        }
                    }
                }
                });
            p.then(value=>{
    
    
                console.log(value);
            },reason=>{
    
    
                console.warn(reason);
            });
        });
    </script>

五、Promise封装fs读取文件操作

封装一个函数 mineReadFile 读取文件内容

  • 参数: path 文件路径
  • 返回: promise 对象
function mineReadFile(path){
    
    
    return new Promise((resolve,reject)=>{
    
    
        // 读取文件
        require('fs').readFile(path,(err,data)=>{
    
    
            if(err) reject(err);
            resolve(data);
        });
    });
}

mineReadFile('./resource/content.txt')
.then((value)=>{
    
    
    console.log(value.toString());
},(reason)=>{
    
    
    console.log(reason);
});

六、util.promisify方法进行promise风格转化

//  引入util模块
const util=require('util');
// 引入fs模块
const fs=require('fs');
//返回一个新的函数
let mineReadFile=util.promisify(fs.readFile);

mineReadFile('./resource/content.txt').then(value=>{
    
    
    console.log(value.toString());
});

七、Promise封装AJAX请求

封装一个函数 sendAJAX 发送 GET AJAX 请求
参数 : URL
返回结果: Promise 对象

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('https://api.apiopen.top/getJok')
   .then(value => {
    
    
       console.log(value);
   }, reason => {
    
    
       console.warn(reason);
   });

八、Promise对象状态属性介绍

promise的状态:实例对象中的一个属性 『PromiseState』

  • pending 未决定的
  • resolved / fullfilled 成功
  • rejected 失败

Promise 对象的值:实例对象中的另一个属性 『PromiseResult』
保存着异步任务『成功/失败』的结果

  • resolve
  • reject

九、Promise工作流程 在这里插入图片描述

十、Promise的API

1.构造函数-then-catch

let p=new Promise((resolve,reject)=>{
    
    
            //  同步调用  先输出111 再输出222
            // console.log('111');

            // 修改promise对象的状态
            reject('error');
        });
        // console.log('222');

        // 执行catch方法  (catch只能指定失败的回调函数)
        p.catch(reason=>{
    
    
            console.log(reason);
        });

2.Promise.resolve()方法

该方法较特殊,相较于then与catch,它属于Promise这个函数对象,并不属于实例对象。
作用:快速得到一个promise对象

  • 如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
  • 如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
let p1 = Promise.resolve(521);
let p2 = Promise.resolve(new Promise((resolve, reject) => {
    
    
     // resolve('OK');
     reject('Error');
 }));
 // console.log(p2);
 p2.catch(reason => {
    
    
     console.log(reason);
 })

3.Promise.reject()方法

作用:快速返回一个失败的promise对象。(无论传入什么,返回的都是失败的Promise)

// let p = Promise.reject(521);
        // let p2 = Promise.reject('iloveyou');
        let p3 = Promise.reject(new Promise((resolve, reject) => {
    
    
            resolve('OK');
        }));
        
        console.log(p3);

4.Promise.all()方法

(promises) => {}
promises:包含 n 个 promise 的数组
注:返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就
直接失败

let p1 = new Promise((resolve, reject) => {
    
    
     resolve('OK');
 })
 // let p2 = Promise.resolve('Success');
 let p2 = Promise.reject('Error');
 let p3 = Promise.resolve('Oh Yeah');
 
 const result = Promise.all([p1, p2, p3]);

 console.log(result);

5.Promise.race()方法

(promises) => {}
promises:包含 n 个 promise 的数组
注:返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

let p1 = new Promise((resolve, reject) => {
    
    
     setTimeout(() => {
    
    
         resolve('OK');
     }, 1000);
 })
 let p2 = Promise.resolve('Success');
 let p3 = Promise.resolve('Oh Yeah');

 const result = Promise.race([p1, p2, p3]);

 console.log(result);

十一、Promise关键问题

1.如何修改对象的状态

let p = new Promise((resolve, reject) => {
    
    
     //1. resolve 函数
     // resolve('ok'); // pending   => fulfilled (resolved)
     //2. reject 函数
     // reject("error");// pending  =>  rejected 
     //3. 抛出错误
     // throw '出问题了';
 });

 console.log(p);

2.能否执行多个回调

当promise状态改变为对应状态时都会调用

let p = new Promise((resolve, reject) => {
    
    
       // resolve('OK');
   });

   ///指定回调 - 1
   p.then(value => {
    
    
       console.log(value);
   });

   //指定回调 - 2
   p.then(value => {
    
    
       alert(value);
   });

3.改变状态与指定回调的顺序问题(不理解)

(1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
(2) 如何先改状态再指定回调? ① 在执行器中直接调用 resolve()/reject()
② 延迟更长时间才调用 then()
(3) 什么时候才能得到数据? ① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据

let p = new Promise((resolve, reject) => {
    
    
   setTimeout(() => {
    
    
       resolve('OK');
   }, 1000);
});

p.then(value => {
    
    
   console.log(value);
},reason=>{
    
    
   
})

4.then方法返回结果由什么决定

由 then()指定的回调函数执行的结果决定
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果

let p = new Promise((resolve, reject) => {
    
    
            resolve('ok');
        });
        //执行 then 方法
        let result = p.then(value => {
    
    
            // console.log(value);
            //1. 抛出错误
            // throw '出了问题';
            //2. 返回结果是非 Promise 类型的对象
            // return 521;
            //3. 返回结果是 Promise 对象
            // return new Promise((resolve, reject) => {
    
    
            //     // resolve('success');
            //     reject('error');
            // });
        }, reason => {
    
    
            console.warn(reason);
        });

        console.log(result);

5.串联多个任务

(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务

let p = new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                resolve('OK');
            }, 1000);
        });

        p.then(value => {
    
    
            return new Promise((resolve, reject) => {
    
    
                resolve("success");
            });
        }).then(value => {
    
    
            console.log(value);
        }).then(value => {
    
    
            console.log(value);   // undefined
        })

6.异常穿透

(1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
(2) 前面任何操作出了异常, 都会传到最后失败的回调中处理

let p = new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                resolve('OK');
                // reject('Err');
            }, 1000);
        });

        p.then(value => {
    
    
            // console.log(111);
            throw '失败啦!';
        }).then(value => {
    
    
            console.log(222);
        }).then(value => {
    
    
            console.log(333);
        }).catch(reason => {
    
       // 在最后指定一个失败的回调
            console.warn(reason); 
        });

7.如何中断promise链

(1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
(2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象

let p = new Promise((resolve, reject) => {
    
    
            setTimeout(() => {
    
    
                resolve('OK');
            }, 1000);
        });

        p.then(value => {
    
    
            console.log(111);
            //有且只有一个方式
            return new Promise(() => {
    
    });
        }).then(value => {
    
    
            console.log(222);
        }).then(value => {
    
    
            console.log(333);
        }).catch(reason => {
    
    
            console.warn(reason);
        });

十二、Promise自定义封装(又称手写Promise)

1.初始结构搭建

2.resolve与reject结构搭建

3.resolve与reject代码实现

4.throw抛出异常改变状态

5.Promise对象状态只能修改一次

6.then方法执行回调

7.异步任务回调的执行(不理解)

8. 指定多个回调的实现

9.同步修改状态then方法结果返回(不理解)

10.异步修改状态then方法结果返回

11.then方法完善与优化

12.catch方法-异常穿透与值传递

13.resolve方法封装

14.reject方法封装

15.all方法封装

16.race方法封装

17.then方法回调的异步执行

18.class版本的实现

十三、async函数

  1. 函数的返回值为 promise 对象
  2. promise 对象的结果由 async 函数执行的返回值决定

十四、await表达式

  1. await 右侧的表达式一般为 promise 对象, 但也可以是其它的值
  2. 如果表达式是 promise 对象, await 返回的是 promise 成功的值
  3. 如果表达式是其它值, 直接将此值作为 await 的返回值

注:

  1. await 必须写在 async 函数中, 但 async 函数中可以没有 await
  2. 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
async function main(){
    
    
  let p = new Promise((resolve, reject) => {
    
    
      // resolve('OK');
      reject('Error');
  })
  //1. 右侧为promise的情况
  // let res = await p;
  //2. 右侧为其他类型的数据
  // let res2 = await 20;
  //3. 如果promise是失败的状态
  try{
    
    
      let res3 = await p;
  }catch(e){
    
    
      console.log(e);
  }
}

main();

十五、async与await结合实践

/**
 * resource  1.html  2.html 3.html 文件内容
 */

const fs = require('fs');
const util = require('util');
const mineReadFile = util.promisify(fs.readFile);

//回调函数的方式
// fs.readFile('./resource/1.html', (err, data1) => {
    
    
//     if(err) throw err;
//     fs.readFile('./resource/2.html', (err, data2) => {
    
    
//         if(err) throw err;
//         fs.readFile('./resource/3.html', (err, data3) => {
    
    
//             if(err) throw err;
//             console.log(data1 + data2 + data3);
//         });
//     });
// });

//async 与 await
async function main(){
    
    
    try{
    
    
        //读取第一个文件的内容
        let data1 = await mineReadFile('./resource/1x.html');
        let data2 = await mineReadFile('./resource/2.html');
        let data3 = await mineReadFile('./resource/3.html');
        console.log(data1 + data2 + data3);
    }catch(e){
    
    
        console.log(e.code);
    }
}

main();

十六、async与await结合发送AJAX请求

//axios
        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);
                        }
                    }
                }
            });
        }

        //段子接口地址 https://api.apiopen.top/getJoke
        let btn = document.querySelector('#btn');

        btn.addEventListener('click',async function(){
    
    
            //获取段子信息
            let duanzi = await sendAJAX('https://api.apiopen.top/getJoke');
            console.log(duanzi);
        });

写在后面

十二-十六开始看不懂了,没怎么看,以后有机会再慢慢看吧。
接下来去学习axios

猜你喜欢

转载自blog.csdn.net/weixin_44286392/article/details/125709644