JeffreyZhao/wind

binding object and $await

Closed this issue · 5 comments

Hi Jeffey,

can you help to have a look at the following two code snippet:

var obj = {a: 'hello'};
obj.funcA = function () {
    console.log('xxx' + this.a);
    $await(Jscex.Async.sleep(5000));
    console.log(2);
};

var obj2 = {a: 'world'};
obj2.funcB = eval(Jscex.compile("async", function () {
    var task = eval(Jscex.compile('async', obj.funcA))();
    $await(task);
}))();

obj2.funcB.start();

and

var obj = {a: 'hello'};
obj.funcA = function () {
    console.log('xxx' + this.a);
    $await(Jscex.Async.sleep(5000));
    console.log(2);
};
var obj2 = {a: 'world'};
obj2.funcB = eval(Jscex.compile("async", function () {
            var task = eval(Jscex.compile('async', function () {obj.funcA();}))();
    $await(task);
}))();
obj2.funcB.start();

in the first suitation, in the obj.funcA method, the this will refer to the window, but i want to refer to the obj object, and in the second code, seems the $await is not available, it show "[WARNING] An unhandled error occurred: ReferenceError: $await is not defined" in firebug console.

Can you give some help? do i use it incorrectly or ?

I've no idea why you wrote code like that. The way to create a Jscex method is simple and standard. You shouldn't compile a function by passing a reference like you did above. You should always use eval(Jscex.compile("async", function () { ... })) to define a Jscex method. And also, please remember that executing a Jscex method will get you an object, it won't execute the code as you write directly, so use obj2.funcB().start(), obj2.funcB is just a method which returns an object when executed.

You requirement is very easy to meet:

var obj = {a: 'hello'};
obj.funcA = eval(Jscex.compile("async", function () {
    console.log('xxx' + this.a);
    $await(Jscex.Async.sleep(5000));
    console.log(2);
}));

var obj2 = {a: 'world'};
obj2.funcB = eval(Jscex.compile("async", function () {
    $await(obj.funcA());
}));

obj2.funcB().start();

No fancy usage at all, just define obj.funcA as a Jscex method and use it in another one.

Hi Jeffrey,

about the last statement in my code "obj2.funcB.start();", i think you miss the "()" in "obj2.funcB = .........()".the obj2.funcB had already been a Task object.

for the reason why i did like that, just think about the scenario: if the obj.funcA is a testcase, and the obj2.funcB is the testframework which execute the testcase.

we would hope the testcase to be as simple as possible, and left the dirty work to framework, that's why i want to create the Task in obj2.funcB and execute it.

but anyway, i think you give me a good suggestion, i will do as your suggestion firstly. it's appreciate if any comments.

Oh I see, but I'm afraid you'd better not eval the code in funcB since it changes the context of funcA. In you specific case you can do:

obj.funcAAsync = eval(Jscex.compile("async", obj.funcA));

But I won't suggest doing that.

Hi Jeff,

again, according yo your suggestion, it can work for the previous example,but here comes a more complicated case:

var obj = {a: 'hello'};
(function () {
    var module = {message: 'in A module'};
    obj.funcA = function () {
        console.log('xxx' + module.message);
        $await(Jscex.Async.sleep(5000));
        console.log(2);
    };
})();

var obj2 = {a: 'world'};
(function () {
    var module = {message: 'in B module'};
    obj2.funcB = eval(Jscex.compile("async", function () {
        obj.task = eval(Jscex.compile('async', obj.funcA));
        $await(obj.task());
    }));

    obj2.funcB().start();
})();

for the previous code snippet, it will print out "xxxin B module", seems the funcA's scope chain have been changed, but as we expected, it should print out in A module, because of the syntax scope of javascript. i think maybe you create a new function when eval(Jscex.compile('async', obj.funcA)); and it's scope is changed, but it contain closure in this case, so it behave incorrectly!

That's exactly why you need to compile and eval in the place you define a method - keep the context as normal JavaScript method. There should be no other usages of compile and eval in Jscex, or you need to understand how everything works then make your own decision.

Basicly you're changing the way Jscex works.