• co源码


    co模块整体包括三部分

    1. 对于几种参数类型的判断,主要判断是否object,array,promise,generator,generatorFunction这几种;

    2. 将几种不同的参数类型转换为promise

    3. 递归执行promise

       module.exports = co['default'] = co.co = co;
       let slice = [].slice; // 多次用到,所以定义成变量; 原文是Array.prototype.slice
      
       // 1. 对于几种参数类型的判断,主要判断是否object,array,promise,generator,generatorFunction这几种;
      
       /**
       * 判断是否为对象
       * 任何数据类型的constructor属性返回创建该对象的函数的引用,实例的constructor属性指向其构造函数,
       */
       function isObject(obj) {
           return obj.constructor === Object;
       }
      
       /**
       * 是否promise
       * promise具有.then方法,.catch方法
       */
       function isPromise(obj) {
           return 'function' === typeof obj.then;   //也可以用 obj.constructor === Promise
       }
      
       /**
       * 是否generator对象,
       * generator具有next,throw,return方法
       */
       function isGenerator(obj) {
           return 'function' === typeof obj.next() && 'function' === typeof obj.throw() && 'function' === typeof obj.return();
       }
      
       /**
       * generator的constructor的name为GeneratorFunction,displayName(非标准)如果设置也为* GeneratorFunction,
       * display相关参考https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/displayName
       *【注意】generator的constructor !== GeneratorFunction , 参考自这里https://blog.csdn.net/sinat_30552885/article/details/85247120
       */
       function isGeneratorFunction(obj) {
           let constructor = obj.constructor;
           if ( !constructor ) return false;
           if ( constructor.name === 'GeneratorFunction' || constructor.displayName === 'GeneratorFunction') return true;
           return isGenerator(obj);
       }
      
       // 2. 将几种不同的参数类型转换为promise
      
      
       // 总括
       function toPromise(obj) {
           if (!obj) return obj;
           if ( isPromise(obj) ) return obj;
           if ( isGenerator(obj) || isGeneratorFunction(obj) ) return co.call(this, obj);  // co的入参接收promise或者generator,因此如果是generator,则直接调用一遍co;
           if ( 'function' === typeof obj) return thunkToPromise.call(this, obj);
           if ( Array.isArray(obj) ) return arrayToPromise.call(this, obj);
           if ( isObject(obj) )  return objToPromise.call(this, obj);
           return obj;
       }
      
       /**
       * thunk => promise
       */
       function thunkToPromise(fn) {
           let ctx = this;
           return new Promise(function(resolve, reject) {
               fn.call(ctx, function(err, res) {
                   if ( err ) reject(err);
                   if ( arguments.length > 2) res = slice.call(arguments,1);
                   resolve(res);
               })
           })
       }
      
       /**
       *  arr => promise
       *  将数组的每一元素变成promise,然后放入到promise.all里统一存储
       */
       function arrayToPromise(arr) {
           return Promise.all(arr.map(toPromise, this));
       }
      
       /**
       *  obj => promise;
       *  obj.constructor 返回创建该对象的函数的引用
       */
       function objToPromise(obj) {
           let results = new obj.constructor();
           let promises = [];
           let keys = Object.keys(obj);
           for ( let i = 0; i < keys.length; i++ ) {
               let key = keys[i];
               let promise = toPromise(this, obj[key]);
               if ( promise && isPromise(promise) ) {
                   defer(promise, key);
               } else {
                   results[key] = obj[key];
               }
           }
           return Promise.all(promises).then(function() {
               return results;
           })
           function defer(promise, key) {
               promises.push(promise.then(function(res) {
                   results[key] = res;
               }))
           }
       }
      
       // 3. 递归执行promise
      
       /**
       * 
       * @param {*} fn 入参是一个promise或者generator
       * @return Promise;
       */
       function co(gen) {
           let ctx = this;
           let args = slice.call(arguments, 1);
           return new Promise(function(resolve, reject) {
               if ( typeof gen === 'function') gen = gen.apply(ctx, args);
               if ( !gen || typeof gen !== 'function' ) resolve(gen);
               onFulfilled();
               function onFulfilled() {
                   let ret;
                   try {
                       ret = gen.next();
                   } catch (e) {
                       return reject(e);
                   }
                   next(ret);
               }
               function onRejected() {
                   let ret;
                   try {
                       ret = gen.throw();
                   } catch (e) {
                       return reject(e)
                   }
                   next(ret);
               }
               function next(ret) {
                   if ( ret.done ) return resolve(ret.value);
                   let value = toPromise.call(this, ret.value);
                   if ( value && isPromise(value)) return value.then(onFulfilled, onRejected);
               }
      
               return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, but the following object was passed: "' + String(ret.value) + '"'));
           })
       }
      
       co.wrapper = function(fn) {
           createPromise.__generatorFunction__ = fn;
           return createPromise;
           function createPromise() {
               return co.call(this, fn.apply(this,arguments))
           }
       }
  • 相关阅读:
    js中用setTimeout写定时炸弹
    javascript函数的形参和实参
    在Mac OS X中配置Apache+PHP+MySQL(转)
    600多万用户密码使用次数统计分析程序
    pgsql数据库创建以及压缩包形式导入导出
    apache中的.htaccess配置示例收集整理
    收集常用的正则表达式及其应用
    采用htpasswd设置验证机制
    用apache做代理时候,可设置请求头信息
    ubuntu在混合环境中创建和配置文件共享
  • 原文地址:https://www.cnblogs.com/zhaowinter/p/10813462.html
Copyright © 2020-2023  润新知