yld

Forget your promises... adopt the yielded programming style

npm install yld
40 downloads in the last week
80 downloads in the last month

yld

Forget your promises, adopt the yielded programming style !

This Node.js module is under MIT License.

Install

$ npm install yld

Concept

yld (pronounced "yielded") is a tool based on that keyword.

Contrary to promises, where developers add functions and disorganize their code, yld allows you to execute instructions linearly.

Each yield pauses the process and allows to retrieve a response from another function ... this is comparable to promise.then().

This programming method avoids to pass the variables from scope to scope, to handle the response.

If you have already tried to use JavaScript asynchonously, you have certainly thought about some answers to these issues.

Callbacks

They often share variables needed to treat the response.

Their other inconvenients are that you have to create functions to handle the success or failure and to forward the result to calling functions. This affects the readability of your code and pollutes it with additional argument.

In order to avoid that, the promises appeared.

Promises

Promises adds a structure to manage the function result, to run functions during the execution, etc..

They are distinguished by the fact that a promise is an object though which methods you pass a whole bunch of functions to handle the execution steps.

So you end up with a lot of functions, themselves sharing internal references.

Thus puzzling your code.

The yield keyword

Reading the future ECMAScript 6 specification, I found an interesting keyword proposal : the yield.

The yield keyword si a new kind of return.

If you create a function containing one or more yield, that function returns a generator.

Note the asterisk following the function word.

The returned generator can be considered as the instruction lists contained by your function. The generator pauses at each yield until you call the next() method.

var generate, generator;

generate = function* generate(value) {
    var message;

    message = 'Hello';
    yield message;
    yield message + ' ' + value;
};

generator = generate('World');

// writes "Hello"
console.log(generator.next());

// calls the next yield, after 2 seconds
setTimeout(function () {
    // writes "Hello World" in your console, after the 2 seconds
    console.log(generator.next());
}, 2000);

In fact, yield builds a two ways communication : the first statement following yield is returned by next() and the variable passed to the second next(variable) is affected to the yield left = operand.

This allow you to send a value to the generator from the current yield and to receive a value there.

var generate, generator;

generate = function* generate() {
    var message, response;

    message = 'Hello';
    response = yield message;
    yield message + ' ' + response;
};

generator = generate();

// writes "Hello"
console.log(generator.next());

// sends some data to the current yield point, after the 2 seconds
setTimeout(function () {
    // sends "World" to the current yield & writes "Hello World" in your console, after the 2 seconds
    console.log(generator.next('World'));
}, 2000);

Finally, the generators also have a throw() method to throw an error.

The yielded programming style

Therefore, I thought it could be possible to assign to the current context (scope) variable the result of an asynchronous function and then continue the process.

Thus, yld was born.

This is a tool that allows you to transform a generator into an instruction list that run one after the other, as if it were a simple function but waiting for the response of asynchronous functions when necessary.

Moreover, it adds a relationship notion between the different scopes and allows you to avoid passing the variables from one scope to another in order to treat the response.

You can see how it works and find exemple files in the examples folder.

As you can see, this requires few functions. You only pass the arguments your function needs and, the process stops at each yield, allowing you to retrieve a value on the same line as the asynchronous function call.

Notes :

The ES6 generators are still a feature to come in JavaScript.

To use yld in Node.js, you need a Node.js version >= 0.11.x, using the --harmony flag.

To use yld in a browser :

The yld function :

var yielded, generator;

yielded = yld(closure);
generator = yielded(/* closure arguments */);
Function yld()
Returns a yielded function used to call the closure, asynchronously
Arguments :
Function closure()
Your function to be called, asynchronously
Return :
Function yielded()
A function to execute your closure, with the arguments of your choice

The closure structure :

Create a step :

var closure;

closure = function () {
    yield; // this makes a step
};

Retrieve a response form an other scope :

var closure

closure = function () {
    var response;

    response = yield;
};

The generator properties :

[FROZEN] Object this.parent

The parent yielded scope (parent.yld & parent.throw are unavailable. Each scope treats them itself)

String set this.throw(error)

Throws an error (a string or an instance of Error)

var closure;

closure = function () {
    this.throw('error message'); // throws the error message
    yield; // unreached point
};

Function this.next()

Sends variables to the next yield response

var closure;

closure = function () {
    var response;

    this.next(123);
    response = yield; // response is 123
};

Function this.nextCb()

Sends variables to the next yield response, usable to retrieve callback arguments

It's a fallback until the appearance of destructuring assignments

See how-it-works-7.js

Function this.yld()

Your this context knows yld as internal method

var closure;

closure = function () {
    var yielded, response;

    yielded = this.yld(function (/* args */) {
        // here, the this.parent.next() is used to send a response to the parent scope
        this.parent.next(123);
    });

    response = yield yielded(/* args */); // response is 123
};

Send a value after a delay :

Bind an absolute integer to generator.next() or generator.nextCb() method.

var closure;

closure = function () {
    var yielded, response;

    yielded = this.yld(function (/* args */) {
        var delayedNext;

        // here, the this.parent.next() is used to send a response to the parent scope, after a delay (2 seconds)
        delayedNext = this.parent.next.bind(2000);

        delayedNext(123); // sends the response
    });

    response = yield yielded(/* args */); // response is 123
};

Requirements :

ES6 Generators support

npm loves you