JavaScript异步编程【下】 -- Generator、Async/await

文章内容输出来源:拉勾教育 大前端高薪训练营

前言

JavaScript异步编程【上】JavaScript异步编程【中】中,我们已经讲到了处理异步编程的两种方法:回调函数 和 Promise。
那么,我们再来介绍两种ES6中新增的处理异步编程的方法:Generator 和 Async/await 。

Generator

Generator 函数是 ES2015 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

基本介绍

生成器(Generator)函数能生成一组值的序列,但每个值的生成是基于每次请求,并不同于标准函数那样立即生成,每当生成器函数生成了一个值,它都会暂停执行但不会阻塞后续代码执行。

特征与语法

  • 特征

    1,function关键字与函数名之间有一个星号;
    2,函数体内部使用yield表达式,生成一个新的值。

  • 语法

    代码示例如下:

    	function * fn () {
    	    console.log('1111');
    	    yield 100
    	    console.log('2222');
    	    yield 200
    	    console.log('3333');
    	    yield 300
    	}
    	const generator = fn()  // 未执行,得到一个生成器对象
    

    function* 这种声明方式(function关键字后跟一个星号)会定义一个生成器函数 (generator function),它返回一个 Generator 对象。

    代码分析

    在上面的代码中,当调用fn函数的时候,会自动返回 Generator 对象,此时使用 generator 进行存储这个对象。然而,生成器函数在执行过程中,一旦遇到yield关键字,函数的执行将会被暂停下来,只有使用 Generator 对象的next()方法,才会让这个函数的函数体开始执行,并且,yield后面的值将会作为 next 的结果返回。

    总的来说就是,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。

    代码示例如下:

    	function* fn () {
    	    yield 100
    	    yield 200
    	    return 300
    	}
    	const generator = fn()  // 未执行,得到一个生成器对象
    	
    	generator.next()  // { value: 100, done: false}
    	generator.next()  // { value: 200, done: false}
    	generator.next()  // { value: 300, done: true}
    	generator.next()  // { value: undefined, done: true}
    

    上面代码一共调用了四次next方法。

    代码分析

    第一次调用,Generator 函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,它的value属性就是当前yield表达式的值100,done属性的值false,表示遍历还没有结束。

    第二次调用,Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield表达式的值200,done属性的值false,表示遍历还没有结束。

    第三次调用,Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)。next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。

    第四次调用,此时 Generator 函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值。

  • 总结

    Generator 函数执行过程中,遇到yield关键字,函数的执行将会被暂停下来,只有调用Generator 对象的next()方法,才会让这个函数继续执行,并且yield后面的值将会以对象的形式进行返回,返回的对象中包含两个属性:一是value,当前的返回的值;二是done,它是一个布尔值,表示是否遍历结束。

yield 与 return

通过上面的描述,可以知道 yield 与 return 一样都可以返回值,那么,他们有何相同点和不同点呢?

  • 相同点

    都能返回紧跟在语句后面的那个表达式的值。

  • 不同点

    1,每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。
    2,一个函数里,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。
    3,正常函数只能返回一个值,因为只能执行一次return;Generator 函数可以返回一系列的值,因为可以有任意多个yield。

Async/await

async/await 是ES2017提供的处理异步函数的方式,它其实是 Generator 函数的语法糖。

  • 语法

    代码示例如下:

    const fn = async function () {
        await 100
        await 200
        return 300
    }
    

可以看到,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await。

async函数对 Generator 函数的改进,体现在以下四点。

  • 1,内置执行器。

    Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

    fn();
    

    上面的代码调用了fn函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。

  • 2,更好的语义。

    async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

  • 3,更广的适用性。

    co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。

  • 4,返回值是 Promise。

    async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

总结

async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值