• Web前端 Promise 入门 【尚硅谷】


    尚硅谷Web前端Promise教程从入门到精通

    资料

    链接:https://pan.baidu.com/s/1pQpaX4OJtRZILJf87pBQpg?pwd=9f8n
    提取码:9f8n

    课程的五大部分内容:

    1.介绍与基本使用

    2.Promise的API

    3.Promise 中的几个关键问题

    4.自定义封装

    5.async和await(异步编程的终极解决方案)

    异步编程

    回调函数的方式:

    • fs 文件操作

      require('fs').readFile('./index.html', (err,data)=>{
           })
      
      • 1
      • 2
    • 数据库操作

    • AJAX

        $.get('/server', (data)=>{
           })
      
      • 1
      • 2
    • 定时器

      setTimeout(()=>{
           }, 2000);
      
      • 1
      • 2

    Promise 的状态

    实例对象中的一个属性 『PromiseState』

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

    Promise 对象的值

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

    • resolve
    • reject

    第 1 章:Promise 的理解和使用

    1.1 Promise是什么?

    1.1.1 理解

    • 抽象表达

      • Promise 是一门新的技术(ES6 规范)
      • Promise 是 JS 中进行异步编程的新解决方案
        备注:旧方案是单纯使用回调函数
    • Promise 的状态改变

      • pending 变为 resolved
      • pending 变为 rejected

    1.1.2. promise 的状态改变

    1. promise 的状态

      1. pending (未决定)
      2. resolved | fulfilled(完成)
      3. rejected (拒绝)
    2. 状态改变

      1. pending 变为 resolved | fulfilled

      2. pending 变为 rejected

    说明: 只有这 2 种, 且一个 promise 对象只能改变一次

    无论变为成功还是失败, 都会有一个结果数据

    成功的结果数据一般称为 value, 失败的结果数据一般称为 reason

    1.1.3. promise 的基本流程

    在这里插入图片描述

    1.1.4. promise 的基本使用

    1. 使用 1: 基本编码流程
    <script>
        // 1) 创建 promise 对象(pending 状态), 指定执行器函数
        const p = new Promise((resolve, reject) => {
       
    // 2) 在执行器函数中启动异步任务
            setTimeout(() => {
       
                const time = Date.now()
    // 3) 根据结果做不同处理
    // 3.1) 如果成功了, 调用 resolve(), 指定成功的 value, 变为 resolved 状 态
                if (time % 2 === 1) {
       
                    resolve('成功的值 ' + time)
                } else {
        // 3.2) 如果失败了, 调用 reject(), 指定失败的 reason, 变为
                    rejected
                    状态
                    reject('失败的值' + time)
                }
            }, 2000)
        })
        // 4) 能 promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
        p.then(
            value => {
        // 成功的回调函数 onResolved, 得到成功的 vlaue
                console.log('成功的 value: ', value)
            },
            reason => {
        // 失败的回调函数 onRejected, 得到失败的 reason
                console.log('失败的 reason: ', reason)
            })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    1.2 为什么要用 Promise?

    1.2.1 指定回调函数的方式更加灵活

    • 旧的: 必须在启动异步任务前指定
    • Promise: 启动异步任务 => 返回Promise对象 => 给Promise对象绑定回调函数(甚至可以任务结束后指定多个回调)

    1.2.2 支持链式调用, 可以解决回调地狱问题

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HkpQZZE0-1661042247432)(G:\Project\Typora\Image\回调地狱.jpg)]

    • 什么是回调地狱?
      回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件

    • 回调地狱的缺点?
      不便于阅读
      不便于异常处理

    • 解决方案?

      Promise链式调用

    • 终极解决方案?

      async/await

    1.3 Promise 初体验

    doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基本使用title>
        <link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    head>
    <body>
        <div class="container">
            <h2 class="page-header">Promise 初体验h2>
            <button class="btn btn-primary" id="btn">点击抽奖button>
        div>
        <script>
            //生成随机数
            function rand(m,n){
         
                return Math.ceil(Math.random() * (n-m+1)) + m-1;
            }
            /**
                点击按钮,  1s 后显示是否中奖(30%概率中奖)
                    若中奖弹出    恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券
                    若未中奖弹出  再接再厉
            */
            //获取元素对象
            const btn = document.querySelector('#btn');
            //绑定单击事件
            btn.addEventListener('click', function(){
         
                //定时器
                // setTimeout(() => {
         
                //     //30%  1-100  1 2 30
                //     //获取从1 - 100的一个随机数
                //     let n = rand(1, 100);
                //     //判断
                //     if(n <= 30){
         
                //         alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券');
                //     }else{
         
                //         alert('再接再厉');
                //     }
                // }, 1000);
    
                //Promise 形式实现
                // resolve 解决  函数类型的数据
                // reject  拒绝  函数类型的数据
                const p = new Promise((resolve, reject) => {
         
                    setTimeout(() => {
         
                        //30%  1-100  1 2 30
                        //获取从1 - 100的一个随机数
                        let n = rand(1, 100);
                        //判断
                        if(n <= 30){
         
                            resolve(n); // 将 promise 对象的状态设置为 『成功』
                        }else{
         
                            reject(n); // 将 promise 对象的状态设置为 『失败』
                        }
                    }, 1000);
                });
    
                console.log(p);
                //调用 then 方法
                // value 值
                // reason 理由
                p.then((value) => {
         
                    alert('恭喜恭喜, 奖品为 10万 RMB 劳斯莱斯优惠券, 您的中奖数字为 ' + value);
                }, (reason) => {
         
                    alert('再接再厉, 您的号码为 ' + reason);
                });
    
            });
    
        script>
    body>
    
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    1、使用 1: 基本编码流程

    <script>
        // 1) 创建 promise 对象(pending 状态), 指定执行器函数
        const p = new Promise((resolve, reject) => {
         
            // 2) 在执行器函数中启动异步任务
            setTimeout(() => {
         
                const time = Date.now()
                // 3) 根据结果做不同处理
                // 3.1) 如果成功了, 调用 resolve(), 指定成功的 value, 变为 resolved 状 态
                if (time % 2 === 1) {
         
                    resolve('成功的值 ' + time)
                } else {
         
                    // 3.2) 如果失败了, 调用 reject(), 指定失败的 reason, 变为rejected状态
                    reject('失败的值' + time)
                }
            }, 2000)
        })
    
        // 4) 能 promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
        p.then(
            value => {
          // 成功的回调函数 onResolved, 得到成功的 vlaue
                console.log('成功的 value: ', value)
            },
            reason => {
          // 失败的回调函数 onRejected, 得到失败的 reason
                console.log('失败的 reason: ', reason)
            })
    script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2、使用 2: 使用 promise 封装基于定时器的异步

    doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基本使用title>
    head>
    <body>
    <script>
        function doDelay(time) {
         
            // 1. 创建 promise 对象
            return new Promise((resolve, reject) => {
         
                // 2. 启动异步任务
                console.log('启动异步任务')
                setTimeout(() => {
         
                    console.log('延迟任务开始执行...')
                    // 假设: 时间为奇数代表成功, 为偶数代表失败
                    const time = Date.now()
                    // 成功了
                    if (time % 2 === 1) {
         
                        // 3. 1. 如果成功了, 调用 resolve()并传入成功的 value
                        resolve('成功的数据 ' + time)
                    } else {
          // 失败了
                        // 3.2. 如果失败了, 调用 reject()并传入失败的 reason
                        reject('失败的数据 ' + time)
                    }
                }, time)
            })
        }
    
        const promise = doDelay(2000)
        promise.then(
            value => {
         
                console.log('成功的 value: ', value)
            },
            reason => {
         
                console.log('失败的 reason: ', reason)
            },
        )
    script>
    body>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    3、使用 3: 使用 promise 封装 ajax 异步请求

    doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基本使用title>
    head>
    <body>
    <script>
        /*
        可复用的发 ajax 请求的函数: xhr + promise
        */
        function promiseAjax(url) {
         
            return new Promise((resolve, reject) => {
         
                const xhr = new XMLHttpRequest()
                xhr.onreadystatechange = () => {
         
                    if (xhr.readyState !== 4) return
                    const {
         status, response} = xhr
                    // 请求成功, 调用 resolve(value)
                    if (status >= 200 && status < 300) {
         
                        resolve(JSON.parse(response))
                    } else {
          // 请求失败, 调用 reject(reason)
                        reject(new Error('请求失败: status: ' + status))
                    }
                }
                xhr.open("GET", url)
                xhr.send()
            })
        }
    
        promiseAjax('https://api.apiopen.top2/getJoke?page=1&count=2&type=video').then(
            data => {
         
                console.log('显示成功数据', data)
            }, error => {
         
                alert(error.message)
            }
        )
    script>
    body>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    代码

    doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>基本使用title>
    head>
    <body>
    <script>
        // 成功的回调函数
        function successCallback(result) {
         
            console.log("声音文件创建成功: " + result);
        }
    
        // 失败的回调函数
        function failureCallback(error) {
         
            console.log("声音文件创建失败: " + error);
        }
    
        /* 1.1 使用纯回调函数 */
        createAudioFileAsync(audioSettings, successCallback, failureCallback)
    
        /* 1.2. 使用 Promise */
        const promise = createAudioFileAsync(audioSettings); // 2
        setTimeout(() => {
         
    
            promise.then(successCallback, failureCallback);
        }, 3000);
    
        /*
        2.1. 回调地狱
        */
        doSomething(function (result) {
         
            doSomethingElse(result, function (newResult) {
         
                doThirdThing(newResult, function (finalResult) {
         
                    console.log('Got the final result: ' + finalResult)
                }, failureCallback)
            }, failureCallback)
        }, failureCallback)
    
        /*
        2.2. 使用 promise 的链式调用解决回调地狱
        */
        doSomething().then(function (result) {
         
            return doSomethingElse(result)
        }).then(function (newResult) {
         
            return doThirdThing(newResult)
        }).then(function (finalResult) {
         
            console.log('Got the final result: ' + finalResult)
        }).catch(failureCallback)
    
        /*
        2.3. async/await: 回调地狱的终极解决方案
        */
        async function request() {
         
            try {
         
                const result = await doSomething()
                const newResult = await doSomethingElse(result)
                const finalResult = await doThirdThing(newResult)
                console.log('Got the final result: ' + finalResult)
            } catch (error) {
         
                failureCallback(error)
            }
        }
    
    script>
    body>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    1.4 Promise实践练习

    1、fs模块

    //
    const fs = require('fs');
    
    //回调函数 形式
    // fs.readFile('./resource/content.txt', (err, data) => {
       
    //     // 如果出错 则抛出错误
    //     if(err)  throw err;
    //     //输出文件内容
    //     console.log(data.toString());
    // });
    
    //Promise 形式
    let p = new Promise((resolve , reject) => {
       
        fs.readFile('./resource/content.txt', (err, data) => {
       
            //如果出错
            if(err) reject(err);
            //如果成功
            resolve(data);
        });
    });
    
    //调用 then 
    p.then(value=>{
       
        console.log(value.toString());
    }, reason=>{
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
  • 相关阅读:
    JAVA毕业设计136—基于Java+Springboot+Vue的房屋租赁管理系统(源代码+数据库)
    有关排序的算法
    redis之如何存储时间序列数据
    Dasviewer软件在浏览模型时能通过经纬度定位点吗?
    用AI在本地给.NET设计几张壁纸
    记录UNIAPP打包苹果iOS·APP
    如何通过pywinauto开始PC端自动化
    JavaScript API 获取当前地理位置
    PPOCRLabel 半标注工具全平台安装使用
    c++ 容器适配器
  • 原文地址:https://blog.csdn.net/weixin_46703850/article/details/126447187