• co & thunkify


    co

    之前在generator中已经介绍过Co了

    戳这里
    http://www.cnblogs.com/cart55free99/p/4893498.html

    co一般和thunkify一起使用 能够使得generator用起来更方便 所以co就是一个generator的流程控制模块
    以fs.readFile作为例子

    先把readFile thunkify一下

    fs.readFile(filename, callback)
    

    变成

    readThunk(filename)(callback)
    

    这样的调用形式

    co的用法

    co(function* (){
    	var fs1 = yield readThunk('a.txt', 'utf8');
    	var fs2 = yield readThunk('b.txt', 'utf8');
    	//...
    })
    

    你可以像Async那样用同步的方式书写异步代码
    这里的fs1 fs2就是 a.txt b.txt文件中的内容
    真奇怪 fs1 fs2 的值应该是由 gen.next() 传入啊,
    难道说 gen.next() 传入了 readThunk得到的文件内容?
    没错 就是这样

    下面简单说说co的源码

    function co(gen) {
      var ctx = this;
      var args = slice.call(arguments, 1)
      return new Promise(function(resolve, reject) {
        gen = gen.apply(ctx, args);
    
        //onFulfilled实际上调用第一个gen.next();
        onFulfilled();
    
    
        //为了能够这样调用 var a = yield asyncFuntion();
        //那么就需要将前一个async的返回值通过 gen.next()传给 变量a
        //也就是将res这个值给a
        function onFulfilled(res) {
          var ret;
          try {
            ret = gen.next(res);
          } catch (e) {
            return reject(e);
          }
          next(ret);
        }
    
    
        function onRejected(err) { ... }
    
        function next(ret) {
          if (ret.done) return resolve(ret.value);
          //将异步函数转为一个Promise对象 value是一个Promise对象
          var value = toPromise.call(ctx, ret.value);
          //判断是否是一个Promise对象 就是看是否有then()
          if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
          
        }
      });
    }
    
    

    可见用一个Promise 来处理异步函数 将异步函数readFile的结果通过Filfilled这个callback再次调用gen.next() 所以fs1 fs2 就是文件内容
    不过即使thunkify之后 至始至终貌似都只向 readThunk传了一个参数 callback呢?

    仔细研究就会发现一般的回调函数都是 function(err, data)的形式 所以co在
    thunkToPromise 中用一个通用的回调函数 不用自己写回调函数了
    这个回调函数就是将 data resolve 并返回一个Promise

    fn就是异步函数

      return new Promise(function (resolve, reject) {
        fn.call(ctx, function (err, res) {
          if (err) return reject(err);
          if (arguments.length > 2) res = slice.call(arguments, 1);
          resolve(res);
        });
      });
    
    

    Promise success的那部分调用 Fulfilled 也就是再次调用了gen.next

    co基本的处理流程就是这样

  • 相关阅读:
    dudu把博客园搞成中国的stackoverflow就牛x大了
    微雨燕双飞,落花人独立 。是什么意思
    Fill Value To List : XML Bean Property « Spring « Java
    Ruby SQLite GUI
    工作流现状
    Windows Phone开发(32):路径之PathGeometry
    《论道HTML5》内容技术分享活动
    Windows Phone开发(30):图形
    wp7资源调用
    Cocos2dx win7 + vs2010 配置图文详解 .
  • 原文地址:https://www.cnblogs.com/cart55free99/p/5187397.html
Copyright © 2020-2023  润新知