neurosnap / cofx

A node and javascript library that helps developers describe side-effects as data in a declarative, flexible API.
MIT License
94 stars 4 forks source link

callEffect assumes non generator with array syntax fn #12

Closed calvinwiebe closed 5 years ago

calvinwiebe commented 5 years ago

First off: thanks for the lib!

I'm attempting to use cofx inside class generator functions. I want to maintain the context of this when using these functions. To maintain context, I use the array style of passing fn: call([obj, 'methodName']). However, it seems that the callEffect handler assumes a non-generator function when you pass the array syntax, and immediately tries to resolve it, instead of testing for a generator and running it. Ex:

const { call, task } = require('cofx');

class TheClass {
    constructor() {

    }

    asyncThing() {
        return new Promise((resolve) => {
            setTimeout(() => resolve(3), 1000);
        })
    }

    * levelThree() {
        const a = yield call(this.asyncThing);
        const b = yield call(this.asyncThing);
        return a + b;
    }

    * levelTwo() {
        const a = yield call([this, 'levelThree']);
        const b = yield call([this, 'levelThree']);
        return a + b;
    }

    * levelOne() {
        const results = yield call([this, 'levelTwo']);
        return results;
    }
}

const c = new TheClass;

task.call(c, c.levelOne)
    .then(results => console.log(results));

If I run this the resulting log is an empty object that outputs immediately. If I change this bit in callEffect to:

let gen;
if (Array.isArray(fn)) {
    const [obj, fnName, ...fargs] = fn;
    gen = obj[fnName](...fargs);
} else {
    gen = fn.call(this, ...args);
}

Then the above code gets all of its generators run, waits for the timeouts, and outputs: 12.

I'm happy to submit a PR if my assumptions here are correct.

neurosnap commented 5 years ago

Thanks for The feedback!

Calling a function using the array syntax is mainly used when the context of this needs to be preserved (we call all functions with a special this).

If you don't care about the context being used them you can call the generator with call(fn, param1, param2).

I haven't come across a reason to call a generator using the special array syntax but you are right it should technically work the same. I'd be great full if you could submit a PR for this functionality.