zoukankan      html  css  js  c++  java
  • ES6知识点整理之----Generator----异步

    所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

    1、异步编程的方法:

    • 回调函数
    • 事件监听
    • 发布/订阅
    • Promise 对象
    • Generator函数

    2、为什么 Node 约定,回调函数的第一个参数,必须是错误对象err(如果没有错误,该参数就是null)?

    原因是执行分成两段,第一段执行完以后,任务所在的上下文环境就已经结束了。在这以后抛出的错误,原来的上下文环境已经无法捕捉,只能当作参数,传入第二段。

    3、Promise 对象就是为了解决 “回调函数地狱”问题而提出的,不是新的语法功能,而是一种新的写法。允许将回调函数的嵌套,改成链式调用。Promise 的最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。

    4、Generator函数,它的奥妙就在其中的yield命令,它是异步两个阶段的分界线。整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。

    5、Generator 函数可以作为异步编程的完整解决方案,有3个特性

    • 可以暂停执行和恢复执行
    • 函数体内外的数据交换:next返回值的 value 属性,是 Generator 函数向外输出数据;next方法还可以接受参数,向 Generator 函数体内输入数据。
    • 错误处理机制

    6、异步任务的封装

    var fetch = require('node-fetch');
    
    //封装
    function* gen(){
      var url = 'https://api.github.com/users/github';
      var result = yield fetch(url);
      console.log(result.bio);
    }
    
    //执行
    var g = gen();
    var result = g.next();
    
    result.value.then(function(data){
      return data.json();
    }).then(function(data){
      g.next(data);
    });

    Thunk 函数

    Thunk 函数是自动执行 Generator 函数的一种方法。

    • 传值调用:先计算表达式的值,再将值传入函数
    • 传名调用:先将表达式传入函数体,只在用到的时候求值

    编译器的“传名调用”实现,往往是将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。

    function f(m) {
      return m * 2;
    }
    
    f(x + 5);
    
    // 等同于
    var thunk = function () {
      return x + 5;
    };
    
    function f(thunk) {
      return thunk() * 2;
    }

    JavaScript 语言是传值调用,它的 Thunk 函数含义有所不同。在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数。

    // 正常版本的readFile(多参数版本)
    fs.readFile(fileName, callback);
    
    // Thunk版本的readFile(单参数版本)
    var Thunk = function (fileName) {
      return function (callback) {
        return fs.readFile(fileName, callback);
      };
    };
    
    var readFileThunk = Thunk(fileName);
    readFileThunk(callback);

    任何函数,只要参数有回调函数,就能写成 Thunk 函数的形式。

    Generator 函数的流程管理

    var fs = require('fs');
    var thunkify = require('thunkify');
    var readFileThunk = thunkify(fs.readFile);
    
    var gen = function* (){
      var r1 = yield readFileThunk('/etc/fstab');
      console.log(r1.toString());
      var r2 = yield readFileThunk('/etc/shells');
      console.log(r2.toString());
    };
    
    
    var g = gen();
    
    var r1 = g.next();
    r1.value(function (err, data) {
      if (err) throw err;
      var r2 = g.next(data);
      r2.value(function (err, data) {
        if (err) throw err;
        g.next(data);
      });
    });

     

    Thunk 函数的自动流程管理

    Thunk 函数真正的威力,在于可以自动执行 Generator 函数。

    function run(fn) {
      var gen = fn();
    
      function next(err, data) {
        var result = gen.next(data);
        if (result.done) return;
        result.value(next);
      }
    
      next();
    }
    
    function* g() {
      // ...
    }
    
    run(g);

    跟在yield命令后面的必须是 Thunk 函数。

    var g = function* (){
      var f1 = yield readFileThunk('fileA');
      var f2 = yield readFileThunk('fileB');
      // ...
      var fn = yield readFileThunk('fileN');
    };
    
    run(g);

    co 模块

    一个小工具,用于 Generator 函数的自动执行。

  • 相关阅读:
    Oracle 11g数据库详解
    1.Oracle数据库查看用户锁表和对表解锁的sql语句
    ORACLE性能优化- Buffer cache 的调整与优化
    excel数据生成sql insert语句
    Python_二叉树
    Python_自定义栈
    Python_内置四种队列
    Python_重写集合
    python_pycharm下拉前置标示
    python_形参何时影响实参
  • 原文地址:https://www.cnblogs.com/adhehe/p/9682661.html
Copyright © 2011-2022 走看看