博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
理解co执行逻辑
阅读量:5887 次
发布时间:2019-06-19

本文共 2763 字,大约阅读时间需要 9 分钟。

对于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 thunkfunction 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

转载于:https://www.cnblogs.com/yuanting0505/p/4633715.html

你可能感兴趣的文章
TCP/IP详解学习笔记(8)-DNS域名系统
查看>>
通过维基API实现维基百科查询功能
查看>>
bootstrap 2
查看>>
Annotation研究的一些学习资料
查看>>
webpack资料
查看>>
DotNet加密方式解析--散列加密
查看>>
OpenSSL使用2(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12概念说明)(转)
查看>>
【前端】:HTML
查看>>
SSM框架——使用MyBatis Generator自动创建代码
查看>>
java数据库操作:JDBC的操作
查看>>
35佳以字体为核心的优秀网页设计作品
查看>>
基于OpenCV的形态学开源库 V0.2
查看>>
在ubuntu下安装和配置vsftpd
查看>>
c#中结构体和类的比较
查看>>
Linux磁盘配额
查看>>
JQuery UI的拖拽功能
查看>>
数据驱动销售——个性化推荐引擎
查看>>
C语言标准库函数qsort那点小事
查看>>
HL7 CDA高级培训
查看>>
Android 调用照相机拍照
查看>>