All files async-action.ts

73.47% Statements 36/49
69.44% Branches 25/36
81.25% Functions 13/16
76.74% Lines 33/43

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77  6x 17x 7x   24x 17x     6x             6x 6x                                         4x 4x   4x 4x       13x 13x 4x 9x 9x 3x   9x       4x 4x 4x 4x 4x     6x   4x 1x 1x 1x 1x            
/*
 * @Author: lijianzhang
 * @Date: 2018-03-31 21:30:17
 * @Last Modified by: lijianzhang
 * @Last Modified time: 2018-08-30 01:43:25
 */
import { runAction } from './action';
import { invariant } from './utils';
 
/**
 * Check if `obj` is a generator.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */
 
function isGenerator(obj?: Iterator<any>) {
    if (!obj) return false;
    return typeof obj.next === 'function' && typeof obj.throw === 'function';
}
 
/**
 * Check if `obj` is a generator function.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */
 
function isGeneratorFunction(obj) {
    const { constructor } = obj;
    if (!constructor) return false;
    if (constructor.name === 'GeneratorFunction' || constructor.displayName === 'GeneratorFunction') return true;
    return isGenerator(constructor.prototype);
}
 
 
async function loopNext(gen, res: IteratorResult<any> = { done: false, value: null }) {
    Iif (res.done) return res.value;
    res = runAction.call(gen, gen.next, res.value);
    Eif (res.value && res.value.then) {
        res.value = await res.value;
    }
    return loopNext(gen, res);
}
 
 
export async function asyncAction(this: any, fn: Function, ...args: Array<any>) {
    invariant(isGeneratorFunction(fn), `${fn.name || 'fn'} must be a generator function`);
    const generator = fn.call(this, ...args);
 
    const res = await loopNext(generator);
 
    return res;
}
 
 
export default function decorativeAsyncAction(target: any, key?: string, descriptor?: any) {
    if (key && descriptor) {
        const { value, initializer } = descriptor;
        if (value) {
            descriptor.value = function wrapAction(...args) {
                return asyncAction.call(this, value, ...args);
            };
        } else if (initializer) {
            descriptor.value = function wrapAction(...args) {
                return asyncAction.call(this, initializer(), ...args);
        E    };
            delete descriptor.initializer;
        }
        return descriptor;
    }
    return (...args: Array<any>) => asyncAction(target, ...args);
}