美文网首页
Generator函数与async总结

Generator函数与async总结

作者: 葶寳寳 | 来源:发表于2018-03-06 17:57 被阅读0次

    Generator函数

    1.理解基本概念

    • 可以把它理解成一个状态机,封装了多个内部状态。
    • 执行 Generator 函数会返回一个遍历器对象,返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
    • 有两个特征:一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态。
    • 调用与普通函数一样,但调用后并不会执行,会返回一个指向内部状态的指针对象(即遍历器对象)。
    • 必须调用遍历器对象的next方法,使得指针移向下一个状态。

    2.yield表达式

    • 是暂停标志。
    • yield表达式只能用在 Generator 函数里面,用在其他地方都会报错。
    • yield表达式本身没有返回值,或者说总是返回undefined

    遍历器对象的next方法的运行逻辑如下。

    (1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
    (2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
    (3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
    (4)如果该函数没有return语句,则返回的对象的value属性值为undefined

    需要注意的是,yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行。

    yield表达式与return语句对比:

    相似: 都能返回紧跟在语句后面的那个表达式的值。
    区别: 每次遇到yield,函数暂停执行,下一次再从该位置继续向后执行,而return语句不具备位置记忆的功能。
    一个函数里面,只能执行一次(或者说一个)return语句,但是可以执行多次(或者说多个)yield表达式。正常函数只能返回一个值,因为只能执行一次returnGenerator 函数可以返回一系列的值,因为可以有任意多个yield。

    3.与 Iterator 接口的关系
    任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数(即Generator函数)。

    4.next()方法参数

    • 可以带一个参数,该参数就会被当作上一个yield表达式的返回值。
    • 在第一次使用next方法时,传递参数是无效的。
    • 如果想要第一次调用next方法时,就能够输入值,可以在 Generator 函数外面再包一层。
         function wrapper(generatorFunction) {
           return function (...args) {
             let generatorObject = generatorFunction(...args);
             generatorObject.next();
             return generatorObject;
           };
         }
      
        const wrapped = wrapper(function* () {
          console.log(`First input: ${yield}`);
          return 'DONE';
        });
      
        wrapped().next('hello!')
      

    5.for...of循环

    • 可以自动遍历 Generator 函数时生成的Iterator对象,且此时不再需要调用next方法。一旦next方法的返回对象的done属性为truefor...of循环就会中止,且不包含该返回对象。

    6.Generator.prototype.throw()

    Generator 函数返回的遍历器对象,都有一个throw方法:

    • 可以在函数体外抛出错误,然后在 Generator 函数体内捕获。
    • 可以接受一个参数,该参数会被catch语句接收,建议抛出Error对象的实例。
    • 被捕获以后,会附带执行下一条yield表达式。也就是说,会附带执行一次next方法。
    • 只要 Generator 函数内部部署了try...catch代码块,那么遍历器的throw方法抛出的错误,不影响下一次遍历。

    Generator函数体内抛出的错误,也可以被函数体外的catch捕获。

    7.Generator.prototype.return()

    Generator函数返回的遍历器对象,还有一个return方法:

    • 可以返回给定的值,并且终结遍历 Generator 函数。
    • 不提供参数,则返回值的value属性为undefined
    • 如果 Generator 函数内部有try...finally代码块,那么return方法会推迟到finally代码块执行完再执行。(即调用return方法后,就开始执行finally代码块,然后等到finally代码块执行完,再执行return方法。)

    8.next()throw()return() 的共同点

    都是让 Generator函数恢复执行,并且使用不同的语句替换yield表达式。

    • next()是将yield表达式替换成一个值。如果next方法没有参数,就相当于替换成undefined
    • throw()是将yield表达式替换成一个throw语句。
    • return()是将yield表达式替换成一个return语句。

    9.yield* 表达式

    • 用来在一个 Generator 函数里面执行另一个 Generator 函数。(表明返回的是一个遍历器对象)
    • yield*后面的 Generator 函数(没有return语句时),是for...of的一种简写形式。有return语句时,则需要用var value = yield* iterator的形式获取return语句的值。
    • 任何数据结构只要有Iterator 接口,就可以被yield*遍历。

    考文档:Generator 函数的语法

    async函数

    实现原理:
    async其实就是Generator函数的语法糖。将generator函数和它的自动执行器co包装了下。

    特点:

    • 内置执行器
    • 将异步代码以同步的写法展示,和更好的语义化(async/await),便于理解;
    • 更广的适用性async函数内部的await后可以是Promise对象,也可以是原始类型(等同于同步操作)。

    用法

    • 像普通函数一样去调用async函数。
    • Generator 函数一样,async 函数会立即返回一个 Promise 对象,可以使用 then方法添加回调函数。
    • 当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。(继发执行)

    使用过程中的需要注意的点:
    1.await后的Promise对象可能是rejected,所以需要有相应的错误处理机制。

    async function func() {
       // 放在try{ } catch(){ }中
       try {
           await getDataPromise();
       } catch(err) {
           console.log(err);
       }
    
       // 或者
       await getDataPromise().catch(err => {
           console.log(err);
       });
    }
    

    2.同样,await不能出现在普通函数中。

    相关文章

      网友评论

          本文标题:Generator函数与async总结

          本文链接:https://www.haomeiwen.com/subject/uoqrfftx.html