node-promise-object icon indicating copy to clipboard operation
node-promise-object copied to clipboard

Port features to ES6

Open icodeforlove opened this issue 10 years ago • 5 comments

I would like to see native support if possible for classes. I need to see what we can get away with first.

icodeforlove avatar Oct 11 '15 16:10 icodeforlove

Maybe the root constructor upon initialization will process all methods? But this wouldn't work when calling static methods.

However if Proxies were supported we could leverage them, its still looking like we may be forced to use a custom constructor still.

icodeforlove avatar Oct 11 '15 16:10 icodeforlove

We can do this with instance methods in the base constructor like this

class Base {
    constructor() {
        var proto = this;
        while (proto = proto.__proto__) {
            if (proto instanceof Object) {
                Object.getOwnPropertyNames(proto).forEach(function (className, instance) {return function (name) {
                    var func = proto[name].bind(instance);
                    proto[name] = function () {
                        console.log(className + ':' + name + ':injection:before');
                        func();
                        console.log(className + ':' + name + ':injection:after');
                    };
                }}(proto.constructor.name, this));
            }
        }
    }
}

As for class methods, i have no idea how to achieve this :(. The shitty way would be to do the following

PromiseObject.create(
    class Square extends Base {
    }
);

var square = new Square();

icodeforlove avatar Oct 15 '15 14:10 icodeforlove

this is a bit of a hack but i guess it works

function wrapMethods (classConstructor, object, wrapper) {
    var className = classConstructor.name;

    Object.getOwnPropertyNames(object).forEach(function (propertyName) {
        if (typeof object[propertyName] !== 'function') {
            return;
        }

        var func = object[propertyName].bind(object);

        object[propertyName] = wrapper(className, propertyName, func);
    });
}

function wrapClass (classConstructor) {
    wrapMethods(classConstructor, classConstructor, function (className, propertyName, func) {
        return function () {
            console.log(className + ':' + propertyName + ':class:injection:before');
            func();
            console.log(className + ':' + propertyName + ':class:injection:after');
        }
    });

    if (classConstructor.name) {
        (new Function('constructorObject', classConstructor.name + ' = constructorObject')).call(null, classConstructor);
    }

    return classConstructor;
}

icodeforlove avatar Oct 15 '15 15:10 icodeforlove

I have decided to create a new project called PromiseClass. I have a solution to all my concerns and it will result in the following syntax for definition

PromiseClass(class Person {
    constructor() {
    }

    *getUser($deferred, id) {
        $deferred.resolve(yield database.query(...));
    }
});

icodeforlove avatar Oct 15 '15 21:10 icodeforlove

I have a working solution but i ended up losing the ability to do the following:

  • pseudo params in constructors :(
  • reopen + super (but you can still use reopen to create wrapped methods)

Its not a show stopper, i also decided to use co, and auto-enable bluebird if it exists

This means that you can actually use yields without having to use bluebird. This also resulted in a 30X increase in speed when doing yielded promises ;). Bluebird is much faster than the native Promise, and co.wrap is much faster than Bluebird.coroutine .

icodeforlove avatar Oct 17 '15 02:10 icodeforlove