zoukankan      html  css  js  c++  java
  • 理解co执行逻辑

    对于co的一个最简版的实现,代码如下 (https://gist.github.com/iwillwen/8488050)

    function co(generator) {
      return function(fn) {
        var gen = generator();
        function next(err, result) {
            if(err){
                return fn(err);
            }
            var step = gen.next(result);
            if (!step.done) {
                step.value(next);
            } else {
                fn(null, step.value);
            }
        }
        next();
       }
    }


    为了理解这个代码,来看一个例子

    var co = require('./co');
    // wrap the function to thunk
    function readFile(filename) {
        return function(callback) {
            require('fs').readFile(filename, 'utf8', callback);
        };
    }
    
    co(function * () {
        var file1 = yield readFile('./file/a.txt');
        var file2 = yield readFile('./file/b.txt');
    
        console.log(file1);
        console.log(file2);
        return 'done';
    })(function(err, result) {
        console.log(result)
    });

    现在就执行顺序来说明一下

    1. 首先是以下部分
     co(function * () {
            var file1 = yield readFile('./file/a.txt');
            var file2 = yield readFile('./file/b.txt');
    
            console.log(file1);
            console.log(file2);
            return 'done';
        })

       这部分代码执行了co函数,并把function*()作为参数generator传入,也就是说,整个部分变成了

    function(fn) {
        var gen = generator();
        function next(err, result) {
            if(err){
                return fn(err);
            }
            var step = gen.next(result);
            if (!step.done) {
                step.value(next);
            } else {
                fn(null, step.value);
            }
        }
        next();
       }(function(err, result) {
        console.log(result)
    })

      这个部分执行这个function,并把

    function(err, result) {
      console.log(result) }

      作为fn的实参传入。

      2. 执行过程中,`var gen`为 `function *()`部分,下面是函数`next()`的声明,之后执行了`next()`函数,此时的`err`和`result`均为空。

      3. `err`为空,因此`if(err)`不执行,执行 `var step = gen.next(result);`,由于`result`这里为空,因此

    var step = gen.next(result)
    step.value
    =readFile('./file/a.txt')
    =function(callback) {
            require('fs').readFile('./file/a.txt', 'utf8', callback);
       };

      4. `step.done `为`false`, 执行`step.value(next);`,即执行

    function(callback) {
        require('fs').readFile('./file/a.txt', 'utf8', callback);
    };

      函数,并`next`作为`callback`传入。`readFile`传入回调函数的参数为`err`和`data`,因此在读取完文件后,`err`和a文件的内容(作为result的实参)传入了 `next`函数并执行。

      5. 与2,3类似,执行`var step = gen.next(result)`,这一步由于result的值为a文件的内容,因此`file1`被赋值为a文件的内容(next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。)。与4类似,err和b文件的内容(作为result的实参)传入`next`函数并执行。

      6. 再次执行到`var step = gen.next(result)`的时候,`file2`被赋予文件b的内容,由于`generator`下面没有`yield`了,于是执行到`return`,`step.value='done'`,`step.done=true`,函数从上次yield语句停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束)。(next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined),done属性的值true,表示遍历已经结束。)

      7. 执行`fn(null, step.value);` 即

    function(err, 'done') {
        console.log('done');
    }();

      8. 因此代码的执行结果为

      content in a.txt

      content in b.txt

      done

  • 相关阅读:
    apache 错误日志
    搭建服务器
    vim配置
    临时表增加查询速度
    如何清空$_POST or $_GET
    hdu 2084
    快速幂
    zjut 1176
    rwkj 1091
    zjut 1090 --------同余定理的应用
  • 原文地址:https://www.cnblogs.com/yuanting0505/p/4633715.html
Copyright © 2011-2022 走看看