Web前端Promise

Promise介绍与使用

Promise是什么?

1.抽象表达:

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

2.具体表达:

  • 从语法上来说:Promise是一个构造函数
  • 从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

异步编程

  • fs文件操作
require('fs').readFile('./index.html',(err,data)=>{})
  • 数据库操作
  • AJAX
$.get('/server',(data)=>{})
  • 定时器
setTimeout(()=>{},2000)

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

1.旧的:必须在启动异步任务前指定

2.promise:启动异步任务=>返回promise对象=>

给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个) 

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

回调地狱

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

特点:不便于阅读,不便于异常处理

Promise实践练习-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)
  })
})
p.then(value=>{
  console.log(value.toString())
},reason=>{
  console.log(reason)
})

 Promise实践练习-AJAX请求

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div class="container">
    <h2 class="page-header">Promise 封装AJAX操作</h2>
    <button class="btn btn-primary" id="btn">点击发送AJAX</button>
  </div>
  <script>
    // 接口地址 http://api.apiopen.top/getJoke
    // 获取元素对象
    const btn=document.querySelector('#btn')
    btn.addEventListener('click',function(){
      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){
            // 控制台输出响应体
            resolve(xhr.response)
          }else{
            // 控制台输出响应状态码
            reject(xhr.status)
          }
        }
      }
        })
        p.then(value=>{
          console.log(value)
        },reason=>{
          console.warn(reason)
        })
      
    })
  </script>
</body>
</html>

封装读取文件函数

/**
 *封装一个函数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(data)
},reason=>{
  console.warn(reason)
})

util.promisify(original)

传入一个遵循常见错误优先的回调风格的函数(即以(err,value)=>...回调作为最后一个参数),并返回一个返回promise的版本

// util.promisify方法
// 引入util模块
const util=require('util')
// 引入fs模块
const fs=require('fs')
// 返回一个新的函数
let mineReadFile=util.promisify(fs.readFile)//让fs.readFile返回一个promise对象,将回调函数风格的方法转为promise风格的方法
mineReadFile('./resource/content.txt').then(value=>{

},reason=>{

})

Promise封装练习

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 封装一个函数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/getJoke').then(value=>{
      console.log(value)
    },reason=>{
      console.warn(reason)
    })

  </script>
</body>
</html>

Promise的状态改变

  1. pending变为resolved
  2. pending变为rejected

说明:只有这两种,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason

 Promise的状态

实例对象中的一个属性PromiseState

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

Promise对象的值

实例对象中的另一个属性 PromiseResult

保存着异步任务(成功或失败)的结果

Promise的基本流程

 API

1.Promise构造函数:Promise(excutor){}

  1. executor函数:执行器(resolve,reject)=>{}
  2. resolve函数:内部定义成功时我们调用的函数value=>{}
  • reject函数:内部定义失败时我们调用的函数reason=>{}

说明:executor会在Promise内部立即同步调用(非异步),异步操作在执行器中执行

2.Promise.prototype.then方法:(onResolved,onRejected)=>{}

  1. onResolved函数:成功的回调函数(value)=>{}
  2. onRejected函数:失败的回调函数(reason)=>{}

说明:指定用于得到成功value的成功回调和用于得到失败reason的失败回调,返回一个新的promise对象

3.Promise.prototype.catch方法:(onRejected)=>{}

  • onRejected函数:失败的回调函数(reason)=>{}

4.Promise.resolve()方法:(value)=>{}

  • value:成功的数据或promise对象

说明:返回一个成功/失败的promise对象

如果传入的参数为非promise类型的对象,则返回的结果为成功promise对象

如果传入的参数为Promise对象,则参数的结果决定了resolve的结果

5.Promise.reject方法:(reason)=>{}

  • reason:失败的原因

说明:返回一个失败的promise对象

无论传入什么样的数值,结果均为失败的promise对象

6.Promise.all方法:(promises)=>{}

  • promises:包含n个promise的数组

说明:返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败

        let p1 = new Promise((resolve, reject) => {
            resolve('ok');
        })

        let p2 = new Promise((resolve, reject) => {
            resolve('hello');
        })

        let p3 = new Promise((resolve, reject) => {
            reject('error');
        })

        let result = Promise.all([p1, p2, p3]);
        console.log(result);

7.Promise.race方法:(promises)=>{} 

  • promises:包含n个promise的数组

说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的结果状态

Promise.race方法是需要传递一个参数,参数为数组,数组中的内容表示的是Promise实例化对象如果有最先到达状态的(pending来更改成fulfilled或者是rejected),不管是成功状态还是失败的状态,都将以这个对象的状态和结果值为准

 

        const p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1);
            }, 1000)
        })
        const p2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject(2);
            }, 3000)
        })
        const p3 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(3);
            }, 5000)
        })
        const result = Promise.race([p3, p1, p2]);
        console.log(result);

promise的几个关键问题

如何改变promise的状态?

  1. resolve(value):如果当前是pending就会变为resolved
  2. reject(reason):如果当前是pending就会变为rejected
  3. 抛出异常:如果当前是pending就会变为rejected
        let p1 = new Promise((resolve, reject) => {
            //成功
            // resolve('success');

            //失败
            // reject('error');

            //抛出异常
            // throw ' 出问题啦,你如果在这么写肯定是有问题的,有没有良心~~~';

            //状态只能更改一次
            reject('error');
            resolve('ok');
        })
        console.log(p1);

一个promise指定多个成功/失败回调函数,都会调用吗?

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

        let p1 = new Promise((resolve, reject) => {
            // resolve('ok');
            // reject('error');
            // throw '异常'
        })
        console.log(p1);

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

改变promise状态和指定回调函数谁先谁后?

(1)都有可能,正常情况下是先指定回调函数再改变状态,但也可以先改状态再指定回调

若执行器函数中为同步任务,则先修改状态,后指定回调

若执行器函数中为异步任务,则先指定回调,在更改状态,更为常见 [promise主要是为了执行异步任务]

(2)如何先改状态再指定回调?

  1. 在执行器中直接调用resolve()/reject()
  2. 延迟更长时间才调用then()

(3)什么时候才能得到数据?

  1. 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
  2. 如果先改变的是状态,那当指定回调时,回调函数就会调用,得到数据

(4)promise.then()返回的新promise的结果状态由什么决定?

  1. 简单表达:由then()指定的回调函数执行的结果决定
  2. 详细表达:
  • 如果抛出异常,新promise变为rejected,reason为抛出的异常
  • 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
  • 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
        const p1 = new Promise((resolve, reject) => {
            resolve('ok');
        })
        const result = p1.then(value => {
            //console.log(value);
            // return value;
            return new Promise((resolve, reject) => {
                //resolve('success');
                reject('error');
            })
        }, reason => {
            console.log(reason);
        })
        console.log(result);

(5)promise如何串连多个操作任务?

  1. promise的then()返回一个新的promise,可以开成then()的链式调用
  2. 通过then的链式调用串连多个同步/异步任务
        new Promise((resolve, reject) => {
            //reject('error');
            resolve('success');
        }).then(value => {
            console.log(value);
            console.log(222);
        }).then(value => {
            console.log(value);//返回结果为undefined
        }).then(value => {
            console.log(value);
        }, reason => {
            console.log(reason);
        })

(6)promise异常穿透

  1. 当使用promise的then链式调用时,可以在最后指定失败的回调
  2. 前面任何操作出了异常,都会传到最后失败的回调中处理
        new Promise((resolve, reject) => {
            console.log(111);
            reject('error');
        }).then(value => {
            console.log(222);
        }).then(value => {
            console.log(value);
        }).then(value => {
            console.log(value);
        }).catch(reason => {
            console.log(reason);
        })

(7)中断promise链

  1. 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
  2. 办法:在回调函数中返回一个pendding状态的promise对象
        new Promise((resolve, reject) => {
            resolve(1);
        }).then(value => {
            console.log(value);
        }).then(value => {
            console.log(22222);
        }).then(value => {
            console.log(33333);
            //return false;
            //throw '异常';
            return new Promise(() => { })
        }).then(value => {
            console.log(44444);
        }).then(value => {
            console.log(55555);
        }).catch(reason => {
            console.log(reason);
        })

async与await

async函数

  • 函数的返回值为promise对象
  • promise对象的结果由async函数执行的返回值决定
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>async函数</title>
</head>

<body>
    <script>
        //以前代码
        // const p1 = new Promise((resolve, reject) => {
        //     resolve('ok');
        // })
        // //只不过是从原来的回调地狱写法修改成了回调函数的链式写法,换汤不换药
        // //使用async结合await的终极目标:就是同步的代码来完成异步的功能
        // p1.then(value => {
        //     console.log(value);
        // }, reason => {
        //     console.log(reason);
        // }).then(value => {
        //     console.log(value);
        // }, reason => {
        //     console.log(reason);
        // })

        //任何的函数都可以被声明成一个async函数
        //因为要实现的就是异步功能(定时器、ajax请求...)
        //可能是要将实现的功能封装到一个函数之中,为了更好的表示函数之中是异步,所以在函数的前面添加一个async
        async function main() {
            //函数的内部可以添加任意的语句来执行,但是其真正的目的主要是为了得到一个Promise对象的状态以及结果值
            // console.log('哈哈哈哈');

            //情况1:返回非Promise对象的数据
            // return 100;

            //情况2:返回的是Promise对象
            //返回的这个Promise实例化对象的状态以及结果值将直接影响结果产生的Promise实例化对象的状态和结果值
            // return new Promise((resolve, reject) => {
            //     // resolve('ok');
            //     reject('error');
            // })

            //情况3:抛出异常
            // throw '出错啦';
            throw new Error('出错啦');
        }
        //调用
        let result = main();

        result.then(value => {
            console.log(value);
        }, reason => {
            console.log(reason);
        })
    </script>
</body>

</html>
  1. await表达式

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

注意:

  • await必须写在async函数中,但async函数中可以没有await
  • 如果await的promise失败了,就会抛出异常,需要通过try...catch捕获处理
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>await表达式</title>
</head>

<body>
    <!--
        1、async函数结合await表达式
           1.1 async函数中不一定要完全结合await
           1.2 有await的函数一定是async函数
        2、await相当于then,可以直接拿到成功的Promise实例化对象的结果值
        3、await一定要写在async函数之中,但是async函数之中可以没有await
        4、如果await表达式后面是Promise实例化对象,则await返回的是Promise的成功的结果值
        5、如果await表达式后面的其他值,则会直接将这个值作为await的返回值
    -->
    <script>
        async function main() {
            //内部执行异步的功能,并且得到成功的结果数据值

            //1、如果await右侧为非Promise类型的数据,await后面的值是什么,得到的结果就是什么
            // let rs = await 100;
            // console.log(rs);

            //2、如果await右侧为Promise成功类型的数据
            // let rs = await new Promise((resolve, reject) => {
            //     resolve('ok');
            // })
            // console.log(rs);

            // let rs = await Promise.resolve('okk');
            // console.log(rs);

            //3、如果await右侧为失败的Promise类型数据,需要try...catch来捕获
            try {
                // let rs = await new Promise((resolve, reject) => {
                //     reject('error');
                // })
                // console.log(rs);

                let rs = await Promise.reject('error');
                console.log(rs);

            } catch (e) {
                console.log(e);
            }
            //有了try...catch后续的代码将继续执行
            console.log(1111);
        }
        //调用
        main();
    </script>
</body>

</html>

使用async和await异步读取文件

//1、导入模块
const fs = require('fs');
const { promisify } = require('util');

//2、创建async函数
async function main() {
    //读取文件
    let myreadfile = promisify(fs.readFile);
    try {
        let one = await myreadfile('./resource/1.txt');
        let two = await myreadfile('./resource/2.txt');
        let three = await myreadfile('./resource/3.txt');
        console.log(one + two + three);
    } catch (e) {
        console.log(e);
    }
}
//调用函数
main();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/843539.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多层全连接神经网络(六)---各种优化算法的变式

梯度下降算法原理此处不做过多说明 梯度下降法的变式 1. SGD 随机梯度下降法是梯度下降法的一个小变形&#xff0c;就是每次使用一批(batch)数据进行梯度的计算&#xff0c;而不是计算全部数据的梯度&#xff0c;因为现在深度学习的数据量都特别大&#xff0c;所以每次都计算…

Lua基础知识入门

1 基础知识 标识符&#xff1a;标识符的定义和 C语言相同&#xff1a;字母和下划线_ 开头&#xff0c; 下划线_ 大写字母一般是lua保留字&#xff0c; 如_VERSION 全局变量&#xff1a;默认情况下&#xff0c;变量总是认为是全局的&#xff0c;不需要申明&#xff0c;给一个变…

docker默认存储地址 var/lib/docker 满了,换个存储地址操作流程

1. 查看docker 存储地址 docker info如下 var/lib/docker2、查看内存大小 按需执行 df -h 找超过100M的大文件 find / -type f -size 100M -exec ls -lh {} \; df -Th /var/lib/docker 查找这个文件的容量 df -h 查找所有挂载点 du -hs /home/syy_temp/*1、df -h 2、sud…

Linux网络——套接字与UdpServer

目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…

全国区块链职业技能大赛国赛考题区块链产品需求分析与方案设计

任务1-1:区块链产品需求分析与方案设计 本任务需要依据项目背景完成需求分析与方案设计,具体要求如下: 依据给定区块链食品溯源系统的业务架构图,对考题进行业务分析,尽可能多的去考虑一个业务系统所需要的模块,使用Visio或思维导图工具展现本系统的基本设计概念和处理流…

基于ffmepg的视频剪辑

1.ffmpeg命令实现视频剪辑 FFmpeg是一个非常强大的视频处理工具&#xff0c;可以用来剪辑视频。以下是一个基本的FFmpeg命令行示例&#xff0c;用于剪辑视频&#xff1a; $ ffmpeg -i ./最后一滴水.mp4 -ss 0:0:20 -t 50 -c copy output.mp4-i ./最后一滴水.mp4 输入文件  …

图像生成(Text-to-Image)发展脉络

这篇博客对 图像生成&#xff08;image generation&#xff09; 领域的经典工作发展进行了梳理&#xff0c;包括重要的一些改进&#xff0c;目的是帮助读者对此领域有一个整体的发展方向把握&#xff0c;并非是对每个工作的详细介绍。 脉络发展&#xff08;时间顺序&#xff0…

探究大语言模型(LLM)漏洞和安全优秀实践

你可能已听说过LLM强势亮相&#xff0c;至少ChatGPT就是代表。 大语言模型(LLM)指语言处理模型。这类模型经过训练&#xff0c;可以执行各种各样的语言任务&#xff1a;翻译、文本生成和问题回答等。 有几个LLM家族和架构&#xff0c;最著名的是GPT(生成式预训练Transformer)…

Grafana :利用Explore方式实现多条件查询

背景 日志统一推送到Grafana上管理。所以&#xff0c;有了在Grafana上进行日志搜索的需求&#xff0c;而进行日志搜索通常需要多条件组合。 解决方案 通过Grafana的Explore的方式实现多条件查询。 直接看操作步骤&#xff1a; 在主页搜索框中输入“Explore” 进入这个界面…

python—日期相差多少天(PythonTip)

[题目描述] 编写一个程序&#xff0c;计算两个日期之间的天数。 导入datetime模块。定义函数calculate_days_between()数&#xff0c;其中有两个参数&#xff1a;(date1, date2)&#xff0c;类型为字符串&#xff0c;格式为YYYY-MM-DD。在函数内&#xff0c;将字符串转换为date…

全面战争模拟器免费下载地址,纯分享

全面战争模拟器以其独特的物理引擎和搞笑的战斗场面吸引了大量玩家&#xff0c;并在游戏社区中赢得了极高的评价。它不仅提供了丰富的策略性玩法&#xff0c;还通过滑稽的视觉效果和搞笑的战斗带来了极大的娱乐性。游戏的沙盒模式和自定义功能更是让玩家能够充分发挥创意&#…

磁盘的作业

1、新添加一块硬盘&#xff0c;大小为5g&#xff0c;给这块硬盘分一个mbr格式的主分区(大小为3g)&#xff0c;给此主分区创建ext2的文件系统&#xff0c;挂载到/guazai1目录&#xff0c;并写入文件内容为"this is fist disk"文件名为1.txt的文件。 [rootwyk ~]# fdis…

02线性表 - 链表

这里是只讲干货不讲废话的炽念&#xff0c;这个系列的文章是为了我自己以后复习数据结构而写&#xff0c;所以可能会用一种我自己能够听懂的方式来描述&#xff0c;不会像书本上那么枯燥和无聊&#xff0c;且全系列的代码均是可运行的代码&#xff0c;关键地方会给出注释^_^ 全…

【时时三省】(C语言基础)函数和数组

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 函数 跟数学里面的函数很相似 数组 一组相同类型的元素的集合 比如把5个整形1-5存起来 int arr&#xff3b;10&#xff3d;&#xff1d;&#xff5b;1&#xff0c;2&#xff0c;3&#x…

逻辑门的题目怎么做?

FPGA语法练习——二输入逻辑门&#xff0c;一起来听~~ FPGA语法练习——二输入逻辑门 题目介绍&#xff1a;F学社-全球FPGA技术提升平台 (zzfpga.com)

高功能自闭症:挑战与潜能并存

高功能自闭症是一种复杂的神经发育障碍&#xff0c;其患者通常在认知、语言和行为方面存在发育障碍&#xff0c;但保持相对正常的社交互动和自理能力。这种疾病由大脑神经发育异常引起&#xff0c;涉及神经递质、脑结构和功能连接等多个方面&#xff0c;导致信息处理和整合困难…

WebRTC音视频-前言介绍

目录 效果预期 1&#xff1a;WebRTC相关简介 1.1&#xff1a;WebRTC和RTC 1.2&#xff1a;WebRTC前景和应用 2&#xff1a;WebRTC通话原理 2.1&#xff1a;媒体协商 2.2&#xff1a;网络协商 2.3&#xff1a;信令服务器 效果预期 1&#xff1a;WebRTC相关简介 1.1&…

SpringCloud的认识和初步搭建

目录 一.认识SpringCloud 二.SpringCloud的部署 2.1开发环境 2.2数据库的建立 2.3SpringCloud的部署 第一步&#xff1a; 创建Maven项目 第二步&#xff1a;完善pom文件 第三步&#xff1a;创建两个子项目 第四步&#xff1a;声明项目依赖以及构建插件 第五步&#xf…

Docker核心技术:容器技术要解决哪些问题

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Docker核心技术 系列文章&#xff1a;容器技术要解决哪些问题&#xff0c;其他文章快捷链接如下&#xff1a; 应用架构演进容器技术要解决哪些问题&#xff08;本文&#xff09;Docker的基本使用Docker是如何实…

Ubuntu20.04从零开搭PX4MavrosGazebo环境并测试

仅仅是个人搭建记录 参考链接&#xff1a; https://zhuanlan.zhihu.com/p/686439920 仿真平台基础配置&#xff08;对应PX4 1.13版&#xff09; 语雀 mkdir -p ~/tzb/catkin_ws/src mkdir -p ~/tzb/catkin_ws/scripts cd catkin_ws && catkin init catkin build cd…