详解 JavaScript 3种异步方式(Promise/async/Generator)

前言

JavaScript 是一个单线程语言,但是也不乏一些异步操作,比如定时器,浏览器事件,回调等。还有耳熟能详的 Promise。自从 ES6 出来之后,提供了更丰富的异步方式。比如 async 函数,Generator 函数。今天就给大家分享一下这3种异步的用法以及区别。

在开始讲解这三个异步函数用法之前,我们通过一个案例来体会一下什么叫异步和同步。

1. 异步

 setTimeout(function (res) {
        console.log(res)
    },3000,"我是3秒钟之后打印")
    setTimeout(function (res) {
        console.log(res)
    },2000,"我是2秒钟之后打印")
    setTimeout(function (res) {
        console.log(res)
    },1000,"我是1秒钟之后打印")

打印结果为:
在这里插入图片描述
众所周知,setTimeout 是异步函数,异步函数的特点之一就是什么时候到点了,就什么时候执行。这跟 Promise 的命名异曲同工,Promise 是承诺的意思。即承诺什么时候执行,就什么时候执行。所以以上的打印顺序根据计时器的时间判定应该是"我是1秒钟之后打印"、“我是2秒钟之后打印”、“我是3秒钟之后打印”。

2. 同步(使用回调将异步变同步)
那么问题来了。如果想让以上的异步执行顺序变成同步的昵? 即打印顺序为 “我是3秒钟之后打印”、“我是2秒钟之后打印”、“我是1秒钟之后打印”。
在 Promise 、async 和 Generator 函数没有出来之前,我们的做法就是使用回调函数。

    function beSync() {
        setTimeout(function (res) {
            console.log(res);
            setTimeout(function (res) {
                console.log(res);
                setTimeout(function (res) {
                    console.log(res)
                },1000,"我是1秒钟之后打印")
            },2000,"我是2秒钟之后打印")
        },3000,"我是3秒钟之后打印")
    }
    beSync();
   

打印结果为:
在这里插入图片描述

3. 分析回调
通过回调实现了将异步变成同步。以上代码有以下几个问题。

  1. 回调里面层层嵌套,代码冗余;
  2. 回调太多,不免有些分辨不出,那个参数来源于那个函数的回调;
  3. 代码之间耦合度太高,一旦有一个回调出现错误,其他回调都会遭殃;
  4. 不能用 try catch 来捕获错误。

基于以上的问题分析,异步解决方案 Promise 函数、async 函数及Generator 函数应运而生。我们来学习一下这3个函数,并使用这3个函数解决以上问题。

一、Promise 函数

  1. 用法
var promise = new Promise(function(reslove,reject){
if(){
	//异步函数成功
	reslove(res)// res是异步函数成功的所获取的参数
	}else{
	//异步函数失败
	reject(err)
	}
})
  1. 示例
var promise = new Promise(function(reslove,reject){
	setTimeout(function(res){
	    reslove(res)
	},1000,'成功')
	});
promise.then(function(res){
 	 console.log(res);//'成功'
})
  1. 解决以上案例
    var promise = new Promise(function (resolve) {
        setTimeout(function (res) {
            resolve(res)
        },3000,"我是3秒钟之后打印")
    })
    promise
        .then(function (res) {
        console.log(res);//"我是3秒钟之后打印"
        return new Promise(function (resolve) {
            setTimeout(function (res) {
                resolve(res)
            },2000,"我是2秒钟之后打印")
        })
    })
        .then(function (res) {
         console.log(res);//"我是2秒钟之后打印"
         return new Promise(function (resolve) {
         setTimeout(function (res) {
            resolve(res)
        },1000,"我是1秒钟之后打印")
    })
        .then(function (res) {
            console.log(res);//"我是1秒钟之后打印"
    })
})

打印结果为:
在这里插入图片描述
Promise 优点是代码结构看上去很清晰,每一个 then 里面的参数都是上一个异步返回的结果对象。缺点是所有的回调都放在 then 里面,没有语义性。

二、Generator 函数

  1. 用法
    Generator 函数有两个明显特征,一是 function 与函数名之间有*号,二是在函数内部使用 yield 表达式,定义不同的内部状态。yield 表示中止执行,而 next 方法表示开启执行,返回的状态值为 yield 后面的表达式结果。
    Generator 函数返回一个遍历器对象。

  2. 示例

function * hello() {
    yield '1';
    yield '2';
    return 'end'
}
var text = hello();
console.log(text.next());
console.log(text.next());
console.log(text.next());

打印结果为:
在这里插入图片描述

  1. 解决以上案例
   function* helloWorld() {
        yield new Promise((resolved)=>{
            setTimeout(function (res) {
                resolved('我是3秒钟之后打印');
            }, 3000);
        });
        yield new Promise((resolved)=>{
            setTimeout(function (res) {
                resolved('我是2秒钟之后打印');
            }, 2000);
        });
        yield new Promise((resolved)=>{
            setTimeout(function (res) {
                resolved('我是1秒钟之后打印');
            }, 1000);
        });
    };
    var hw = helloWorld();
    hw.next().value
        .then(function (res) {
            console.log(res);
    })
        .then(function () {
        hw.next().value.then(function (res) {
            console.log(res);
        })
        .then(function () {
        hw.next().value.then(function (res) {
            console.log(res);
         });
        })
    })

在这里插入图片描述

三、async 函数

  1. 用法
    async 函数 是 Generator 函数的语法糖,它只是将 Generator 函数中的 * 变成了async ,yield 变成了 await,更具有语义性。
    async 函数直接执行,不需要通过 next。
    async 函数返回的是一个 promise 对象,可以使用 then 方法添加回调函数。

  2. 示例

  async function func() {
        return 'hello';
    }
    func().then(function (res) {
        console.log(res)//'hello'
    })
  1. 解决以上案例
    async function helloWorld() {
        await new Promise(function (resolve) {
            setTimeout(function (res) {
                console.log(res);
                resolve(res)
            }, 3000, '我是3秒钟之后打印');
            });
        await new Promise(function (resolve) {
            setTimeout(function (res) {
                console.log(res);
                resolve(res)
            }, 2000, '我是2秒钟之后打印');
        });
        await new Promise(function (resolve) {
            setTimeout(function (res) {
                console.log(res);
                resolve(res)
            }, 1000, '我是1秒钟之后打印');
        });
    };
    helloWorld()

打印结果为:
在这里插入图片描述

  • 9
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Promiseasync/await 是 JavaScript 中处理异步操作的两方法。 Promise 是一个表示异步操作的对象,它可以有三状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。通过 Promise,我们可以更好地处理异步操作的结果。 async/await 是基于 Promise 的语法糖,它使得异步代码看起来更像是同步代码。async 函数返回一个 Promise 对象,并使用 await 关键字来等待 Promise 对象的解决(即 Promise 进入 fulfilled 状态)。 下面是一个使用 Promise 的例子: ``` function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { const data = 'Data fetched successfully'; resolve(data); }, 2000); }); } fetchData() .then(data => { console.log(data); }) .catch(error => { console.error(error); }); ``` 下面是相同功能的使用 async/await 的例子: ``` function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { const data = 'Data fetched successfully'; resolve(data); }, 2000); }); } async function getData() { try { const data = await fetchData(); console.log(data); } catch (error) { console.error(error); } } getData(); ``` 在上面的例子中,fetchData 函数返回一个 Promise 对象。在第一个例子中,我们使用 then 和 catch 方法来处理 Promise 对象的结果和错误。而在第二个例子中,我们使用 async/await 来等待 fetchData 函数的解决,并使用 try/catch 来处理异常情况。 总的来说,Promiseasync/await 都是用于处理异步操作的方法,它们各有特点,可以根据具体需求选择使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值