Gray Zhang (2015-05-24T03:38:26.000Z)
Sorry for some confusing descriptions, IoC means Inversion of Control here, I’d like to put all code together here:

// A simple implement of IoC
ioc.getComponent = (name) {
    return new Promise((resolve) => {
        let iocConfig = parseConfig(name);
        let moduleId = iocConfig.module;
        require([moduleId], function (ModuleClass) {
            let instance = new ModuleClass();
            injectProperties(instance, iocConfig);
            resolve(instance);
        });
    });
}

let inject = (name) => {
    return (target, key, descriptor) => {
        // target = hero
        // key = 'weapon'
        // Use initializer to get the property value
        descriptor.initializer = () => {
            return ioc.getComponent(name);
        };
    };
};

class Hero {
    // We need a knife from ioc as this hero's weapon
    @inject('knife')
    weapon = null;
     
    hit(enemy) {
        // Problem here
        enemy.heath -= this.weapon.power - enemy.defense;
    }
}
The problem is, as I know, when a decorator implements the descriptor.initializer the property value should be the return value of this initializer, however the initializer should be sync which directly returns the value but not a promise or a async function, we can’t await for a descriptor.initializer

In this case, in my hit method, the this.weapon is a Promise but not a knife instance, Promise does not have e a power property so hit method fails, I may correct the code:

hit(enemy) {
    return this.weapon.then((weapon) => {
        emeny.heath -= weapon.power - enemy.defense;
    });
}
It’s OK, I just wait for this.weapon to resolve, but then my hit method becomes async, and everything based on @inject property should be async, which is not actually what I want.

Is the decorator idea based on extended property descriptors actually being used, e.g., with Babel? Sorry if I missed it.
Decorator is now supported with Babel 5.0 and I was trying this these days, expecting it could be integrated with our IoC framework, just as how Spring works in Java.



Best regards

Gray Zhang



在 2015年5月24日 上午2:54:43, Eich Brendan (brendan at mozilla.org) 写到:

Gray Zhang wrote:  
>  
> Hi all:  
>  
> I’m wondering if there is any way to combine a class decorator and an  
> async process together? A common case would be a generic IoC  
> implementation:  
>  

First, too many undefined terms and made-up syntax extensions just makes  
for confusion. Can you define "async process"? To optimize I'll assume  
you mean async function, a function returning a promise.  

> Since in JavaScript IoC  
>  

IoC = Inversion of Control -- just checking!  

> we load runtime modules async by a config file, the interface may be:  
>  
> |{Promise} ioc.getComponent({string} componentName)  
> |  

Nicer to use reserved type annotation syntax:  

| ioc.getComponent(componentName: string): Promise|  


I hope that's what {T} D means!  

> which resolves the returned Promise giving required instance of  
> |componentName|, and this is a method that cannot be sync since we  
> need a config file to map |componentName| to its implementing module  
> and load the module lazily (for performance reason)  
>  
> This is an async process so if we add a decorator to a class property:  
>  
> |function inject(name) {  
> return (target, key, descriptor) {|  

Missing `function` after `return`?  

> |  
> // Note this returns a promise, not the actual property value  
> descriptor.initializer = () => ioc.getComponent(name);  
> }  
> }  
>  
> class Hero {  
> @inject('knife')  
> weapon = null|  

So the decorator calls the anonymous function with key='knife',  
target=instance-of-Hero, and descriptor the property descriptor,  
extended with .initializer?  

BTW the idea of using property descriptors for decorators got push-back  
and an alternative suggestion at the March TC39 meeting.  

> |  
>  
> hit(enemy) {  
> enemy.heath -= (this.weapon.power - enemy.defense);  
> }  
> }  
> |  
>  
> This code may not work, but nobody likes there injected properties to  
> be all async getters and all code logics become unnecessarily complex  
> by introducing so many async processes  
>  

Have you read about `await` and `async` in ES7?  

> How so we think of such common case, should I just make the  
> |ioc.getComponent| sync without considerations to performance,  
>  

"performance" is not really accurate: responsiveness and even deadlock  
avoidance come to mind. If you're talking about a browser API, then you  
can't do sync loading (apart from bad old sync XHR), so async/await is  
the way to go.  

> or should I give up the decorator solution?  
>  

Is the decorator idea based on extended property descriptors actually  
being used, e.g., with Babel? Sorry if I missed it.  

/be  
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150524/dbfd82ba/attachment-0001.html>
dignifiedquire at gmail.com (2015-05-30T22:50:26.047Z)
Sorry for some confusing descriptions, IoC means Inversion of Control here, I’d like to put all code together here:
```js
// A simple implement of IoC
ioc.getComponent = (name) {
    return new Promise((resolve) => {
        let iocConfig = parseConfig(name);
        let moduleId = iocConfig.module;
        require([moduleId], function (ModuleClass) {
            let instance = new ModuleClass();
            injectProperties(instance, iocConfig);
            resolve(instance);
        });
    });
}

let inject = (name) => {
    return (target, key, descriptor) => {
        // target = hero
        // key = 'weapon'
        // Use initializer to get the property value
        descriptor.initializer = () => {
            return ioc.getComponent(name);
        };
    };
};

class Hero {
    // We need a knife from ioc as this hero's weapon
    @inject('knife')
    weapon = null;
     
    hit(enemy) {
        // Problem here
        enemy.heath -= this.weapon.power - enemy.defense;
    }
}
```
The problem is, as I know, when a decorator implements the descriptor.initializer the property value should be the return value of this initializer, however the initializer should be sync which directly returns the value but not a promise or a async function, we can’t await for a descriptor.initializer

In this case, in my hit method, the this.weapon is a Promise but not a knife instance, Promise does not have e a power property so hit method fails, I may correct the code:
```js
hit(enemy) {
    return this.weapon.then((weapon) => {
        emeny.heath -= weapon.power - enemy.defense;
    });
}
```
It’s OK, I just wait for this.weapon to resolve, but then my hit method becomes async, and everything based on @inject property should be async, which is not actually what I want.

Is the decorator idea based on extended property descriptors actually being used, e.g., with Babel? Sorry if I missed it.
Decorator is now supported with Babel 5.0 and I was trying this these days, expecting it could be integrated with our IoC framework, just as how Spring works in Java.



Best 

Gray Zhang