JavaScript异步Promise、Async、await使用举例详解

 更新时间:2025年04月10日 09:55:35   作者:Dragon Wu  
Promise 和 async/await 无疑是前端异步编程领域的两大得力工具,下面这篇文章主要介绍了JavaScript异步Promise、Async、await使用举例详解的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、JS里的同步异步

fun1();
fun2();
fun3();

如以上代码,在同步情况下三个函数应该是依次执行的,fun1执行完执行fun2,最终执行fun3。

什么是异步呢?异步就是大家各做各的,互不干扰,无需互相等待。

但需注意,各做各的,并不意味着乱序。它依然是顺序执行的。只不过,fun1没执行完,fun2已经开始执行了。

JS里的常见异步函数有:settimeout、fetch、setInterval等。

二、Promise 

Promise中文意思是承诺,在JS中,可以通俗理解为:把这个任务(函数)交给我,我来完成。

1、状态

Promise 的三种状态:pending(等待中)、fulfilled(成功)、rejected(失败),且状态改变是不可逆的。

    const p=new Promise((resolve,reject)=>{
       resolve("你的成功结果")  //执行更改后Promise状态变成fulfilled
       //reject("失败的结果")  //执行更改后Promise状态变成rejected
       //throw 1            //抛出异常和reject的效果一样
   })

   p.then(res=>res)
       //then直接返回会返回包含返回结果的Promise对象,可以通过.then()继续获取
   .then(res=>{
       //res对应resolve里的值
       console.log("fulfilled状态时打印")
       //以下执行可以返回状态为rejected的Promise给下一级继续执行
       return new Promise((resolve,reject)=>reject("执行出错"))
   }).catch(error=>{
       //error对应reject里的内容
       console.log("rejected状态时打印")
   }).finally(()=>{
       console.log("无论成功还是失败都会打印")
   })

2、all()、race()、any()

先一句话描述以下Promise.all()、Promise.race()、Promise.any()的区别:

(1) Promise.all() 中的Promise序列会全部执行通过才认为是成功,否则认为是失败;

(2) Promise.race() 中Promise序列中第一个执行完毕的是通过,则认为是成功,如果第一个执行完毕的Promise是rejected,则认为失败;

(3) Promise.any() 中Promise序列只有有一个执行通过,则认为成功,如果全部拒绝,则认为失败。

用一张图来说明all()、any():

any和all类似,区别在于any只要有一个成功就返回成功的结果。

用一张图来说明race():

Both resolve, but promise2 is faster ,从这里可以看出端倪。顾名思义,Promse.race 就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

3、简单案例

通过简单案例了解:

    //Promise用法
    const param1 = "normal"; 
    const param2 = "error"; // 第二种情况
    //1. 创建Promise类的对象
    const promise01 = new Promise(function customFun(successFun, failFun) {
        if (param1 === "normal") {
            successFun("自定义成功的函数执行了!")
        } else { //失败和成功的逻辑都是自定义的
            failFun("自定义失败的函数执行了!")
        }
    })
    const promise02 = new Promise(function customFun(successFun, failFun) { // 第二种情况
        if (param2 === "normal") {
            successFun("自定义成功的函数执行了!")
        } else { //失败和成功的逻辑都是自定义的
            failFun("自定义失败的函数执行了!")
        }
    })
    //2. 执行Promise的返回结果
    promise01.then(result => {
        console.log(result)
    }).catch(error => {
        console.log(error)
    })
    promise02.then(result => {  // 第二种情况
        console.log(result)
    }).catch(error => {
        console.log(error)
    })

可以看到控制台打印如下:

第一种情况走自定义成功的逻辑,第二种情况走自定义失败的逻辑。

4、异步执行案例

    //异步常见案例
    const promise03 = new Promise(() => {
        console.log("This is Promise constructor.")

        setTimeout(() => {
            console.log("Timeout executed!")
        }, 3000)
    })
    promise03.then(result => {
        console.log(result)
    })

    console.log("Test Demo.")

控制台输出:

可以清晰地看到,在Promise被执行时,构造信息就已经打印了,之后,顺序执行了Test Demo, 等待3秒后系统再执行了setTimout里的逻辑。

5、解决异步嵌套繁琐的场景

    //Promise来规范Timeout嵌套调用的阅读性差问题
    const promise04 = new Promise((successFun, failFun) => {
        setTimeout(() => {
            successFun("timeout 333")
        }, 3000)
    })
    const promise05 = promise04.then((res) => {

        console.log(res)

        return new Promise((successFun, failFun) => {
            setTimeout(() => {
                successFun("timeout 222")
            }, 2000)
        })

    })

    promise05.then(res => {
        console.log(res)
    })

    console.log("Test Demo.")

控制台打印:

可以看到,首先打印了Test Demo,3秒后执行了第一各Promise里的内容,执行完第一个Promise里的内容后,再过2秒执行了第二各Promise里的内容。这比setTimout的多层嵌套,可读性更好。

三、async和await

async必须用来修饰函数,用来表示该函数是一个异步函数,await必须和async配套使用。await专门用来修饰Promise的实例化对象。

1、async返回类型

    //async有返回类型时,以Promise形式返回
    async function asyncDemo01Fun(){
        return "Demo01"
    }

    async function asyncDemo02Fun(){
        return Promise.resolve("Demo02")
    }

    console.log(asyncDemo01Fun())
    console.log(asyncDemo02Fun())

打印结果:

可以看到,直接返回结果和利用Promise.resolve返回结果是一样的。

由async修饰的函数,在有返回值时都会直接返回Promise对象,而非直接返回值。

2、async与await结合使用的简单案例

    //async和await的案例Demo
    async function asyncFun1() {
        const p = new Promise((successFun, failFun) => {
            setTimeout(() => {
                successFun({num: 1})
            }, 3000)
        })

        let obj = await p;

        console.log(obj)
    }

    asyncFun1()

    console.log("Test Demo.")

打印结果:

可以看到,当有await修饰Promise返回对象时,会等待Promise对象执行完成后,再返回结果给对象,最终将获取到的对象值在3秒后打印。

当有await修饰Promise对象时,系统会等待返回值后再返回对象,继续执行。实际上是将异步处理的事件处理完成后再继续执行同步代码。

3、解决异步嵌套问题

    //async和await的案例Demo
    async function asyncFun2() {
        const p1 = new Promise((successFun, failFun) => {
            setTimeout(() => {
                successFun("Demo 333")
            }, 3000)
        })

        let obj1 = await p1;
        console.log(obj1)

        const p2 = new Promise((successFun, failFun) => {
            setTimeout(() => {
                successFun("Demo 222")
            }, 2000)
        })

        let obj2 = await p2;
        console.log(obj2)
    }

    asyncFun2()

    console.log("Test Demo.")

控制台打印:

可以看到,首先打印了Test Demo,3秒后执行了第一各Promise里的内容,执行完第一个Promise里的内容后,再过2秒执行了第二各Promise里的内容。这比setTimout的多层嵌套,可读性更好。

4、批量请求优化

以下是同步获取请求结果的案例:

     const batchReq=async ()=>{
        const url="https://example.com/api/demo"
        let rep1=await fetch(`${url}/1/`)
        let json1=await rep1.json()
        let name1=await json1.data.name

        let rep2=await fetch(`${url}/2/`)
        let json2=await rep1.json()
        let name2=await json1.data.name

        let rep3=await fetch(`${url}/3/`)
        let json3=await rep1.json()
        let name3=await json1.data.name

        console.log(name1)
        console.log(name2)
        console.log(name3)
    }

以上代码在执行的过程中,由于加了await进行修饰,会依次进行请求,1执行完2执行最后3执行。

如要实现批量请求同时处理,可以参考以下代码:

    const batchReq = async () => {
        try {
            const url = "https://example.com/api/demo"
            let resp = await Promise.all([fetch(`${url}/1/`), fetch(`${url}/2/`), fetch(`${url}/3/`)])
            let jsons = resp.map(res => res.json())
            let values = await Promise.all(jsons)

            values.map(value => {
                console.log(value.data.name)
            })
        } catch (error) {
            console.log(error)
        }
    }

这样写便可以批量发送请求了。

总结

到此这篇关于JavaScript异步Promise、Async、await使用的文章就介绍到这了,更多相关JS异步Promise、Async、await内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • js实现可旋转的立方体模型

    js实现可旋转的立方体模型

    这里给大家分享的是通过js脚本来控制页面中的正方体转动特效,用户可以点击按钮向右转动,也可以向下转动,结合自己的需求控制即可。效果非常棒,这里推荐给大家
    2016-10-10
  • JavaScript实现定时隐藏与显示图片的方法

    JavaScript实现定时隐藏与显示图片的方法

    这篇文章主要介绍了JavaScript实现定时隐藏与显示图片的方法,可实现javascript定时关闭图片的功能,涉及javascript针对页面元素属性定时操作的相关技巧,需要的朋友可以参考下
    2015-08-08
  • 解决页面js接受Long型损失精度问题(最新解决方案)

    解决页面js接受Long型损失精度问题(最新解决方案)

    这篇文章主要介绍了解决页面js接受Long型损失精度问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  •  JavaScript 数据结构之散列表的创建(1)

     JavaScript 数据结构之散列表的创建(1)

    这篇文章主要介绍了 JavaScript 数据结构之散列表的创建,文章围绕主题相关内容展开详细的介绍,需要的小伙伴可以参考一下
    2022-04-04
  • js实现点击注册按钮开始读秒倒计时的小例子

    js实现点击注册按钮开始读秒倒计时的小例子

    js实现点击注册按钮开始读秒倒计时的小例子,需要的朋友可以参考一下
    2013-05-05
  • 前端大文件分片下载具体实现方法(看这一篇就够了)

    前端大文件分片下载具体实现方法(看这一篇就够了)

    本文介绍了在浏览器中下载大文件的技术方案,包括分片下载、断点续传、进度条显示、取消及暂停下载和文件合并等功能,分片下载可以降低网络传输中断的风险,并减少内存占用,需要的朋友可以参考下
    2024-10-10
  • js关闭当前页面(窗口)的几种方式总结

    js关闭当前页面(窗口)的几种方式总结

    js关闭当前页面(窗口)的几种方式总结,需要的朋友可以参考一下
    2013-03-03
  • js删除对象中的某一个字段的方法实现

    js删除对象中的某一个字段的方法实现

    这篇文章主要介绍了js删除对象中的某一个字段的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • JavaScript中子对象访问父对象的方式详解

    JavaScript中子对象访问父对象的方式详解

    js中虽然没有传统面向对象的编程语言里子类访问父类的特殊语法,但是我们可以根据需要造一个,接下来本文给大家分享在JavaScript中子对象访问父对象的方式,需要的朋友可以参考下
    2016-09-09
  • ts中的void和never类型及区别

    ts中的void和never类型及区别

    void类型和never类型都是ts新增的类型,这两者的共同点是都常见用于声明函数的返回值的类型,这里我们把它们两放在一起介绍有助于大家区分,这篇文章主要介绍了ts中的void和never类型及区别,需要的朋友可以参考下
    2023-05-05

最新评论