0.1.4 • Published 8 years ago

gen-async v0.1.4

Weekly downloads
-
License
MIT
Repository
-
Last release
8 years ago

gen-async

中文文档

gen-async makes it possible to use generator rather than callback to fulfil asynchronous logic. It is largely inspired by co since both modules use promise recruition to handle asynchronous logic.So if you just want to study or prefer a more tiny module to use you could install co instead. The difference is gen-async provides some small but useful features and the codes are in ES6 style. Meanwhile the design of 'Future' is enlighten by Tornado(a Python framework)

You can follow this project on Github and I am also glad to discuss with you through E-mail: adavindes@gmail.com

Version

v0.1.4: fix error handle problems when your wrapper is nested.

Install

npm install gen-async

Basic Usage

The traditional callback-style code is like below:

asynchronousFunction(arg1, arg2, function(error, data) {
    if (error) {
        ...
    }
    
    doSomething(data);
});

It isn't complicated enough, But what if you have nested callbacks? like:

func1(arg1, agr2, callback() {
    func2(arg1, arg2, callback() {
        func3(arg1, arg2, callback() {
            ...        
        });
    });
});

Using gen-async, you can write with generator easier to read. Firstly you need to require gen-async module:

const GenWrap = require("gen-async");

Then generate a wrapper object:

var wrapper = GenWrap.genWrap(function* () {
    var result = yield asynchronousFunction;
    doSomething(result);
});

At last just run it:

wrapper.run();

We use fs.readFile as an example:

function* readFile() {
    yield GenWrap.normalizeFunction(fs.readFile)(file_path, encoding); // normalizedFunction will be explained later
    // Do something 
}

var wrapper = GenWrap.genWrap(readFile);
wrapper.run();

Of course you can just write like:

GenWrap.genWrap(readFile).run();

Future

No matter it returns err or data, what you get from wrapper is a 'Future'(this progress is also asynchronous).You can decide the later logic based on the 'state' of 'Future'. And the final result of wrapper is stored as 'future.result'.

normalize

Compared with co, gen-async provides the process of normalize for function, so that you can normalize function like fs.readfile to make it can be used in asynchronous flow.

var normaliziedFunc = GenWrap.normalize(fs.readFile);

Then code like this,you don't need to pass callback argument:

var wrapper = GenWrap.genWrap(function* () {
    var result = yield normalizedFunc(file_path, encoding);
    doSomething(result);
});

Very sorry that I am still working for a more general way to normalize.Now only function with callback argument like 'function(error, data)' can be normalized. And be careful if your function has two arguments before the callback and you only need to pass one, pass the another as null.

pause&resume

When you use generator for fulfill asychronous logic, the generator function will be invoked at one time(not use next() to iterate). So it seems the original feature of generator cannot be used any more.

To solve it, gen-async provides pause and resume features:

var wrapper = GenWrap.genWrap(function* () {
    var file = yield GenWrap.normalize(fs.readFile)(file_path, encoding);
    console.log(file);
    yield GenWrap.pause();
    var file2 = yield GenWrap.normalize(fs.readFile)(file_path2, encoding);
    console.log(file2);
});

var outwrapper = GenWrap.genWrap(function* () {
    var result = yield wrapper.run();
    var result.next();
    ...
    wrapper.resume();
});
outwrapper.run();

You can see below in the first wrapper:

yield GenWrap.pause();

Now the generator is paused and it will return a generator object(not a Future), so in outwrapper:

var result = yield wrapper.run();    

'result' is a generator object, and you can use next() to it.

If you want to resume the asynchronous flow again, just:

wrapper.resume();

Subscriber&Publisher

gen-wrap provides a Subscription&Publisher model, first just add subscription:

GenWrap.addSubscription(key, subscriberFunction());

When run wrapper, just add the same key:

wrapper.run(key);

After wrapper is finished, subscriberFunction will be invoked.

Of course you can pass an array:

wrapper.run([key1, key2]);
0.1.4

8 years ago

0.1.3

8 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago