消除你对Wind.js的疑虑
发布于 3年前 作者 jin52yang 4808 次浏览

eval is (always) evil

eval大概也算是整个ECMAScript语言中最强大的一个方法, 他就像是一个完整的ECMAScript解析器。你说它evil,我也承认这个 方法会存在危险,有可能带来安全问题,特别是在用它执行用户输入 数据的情况下。但Wind.js是用eval来运行已经“编译”后的代码, 让你更舒服顺畅的来编写异步回调的代码。这些代码是你自己写的, 所以不必担心代码注入、跨站脚本攻击这样的安全问题。没有这这个 困扰和担忧,我相信eval应该是美好的。

API太丑,eval为什么不封装?

通过eval执行的代码是被认为是包含该次调用的执行环境的一部分, 因此被执行的代码具有与该执行环境有着相同的作用域链。

var Wind = require("wind");

var msg = 'hello world';
eval("console.log(msg)");//hello world

var msg = 'hello world';
var newFunc = eval(Wind.compile("async", function () { 
    console.log(msg);
}));
newFunc().start();//hello world

变量msg是在eval外定义的,但eval中还是能够打印"hello world"。 如果包装起来如法访问到msg这个变量。

var Wind = require("wind");

var vm = require("vm");
var sandbox = {
      Wind: Wind,
      console:console
};

function $async(fun){
    var script = vm.createScript(Wind.compile("async", fun));
    return script.runInNewContext(sandbox);
}

var msg = 'hello world';
var newFunc = $async(function () { 
    console.log(msg);
});
newFunc().start();//[WARNING] An unhandled error occurred: ReferenceError: msg is not defined

上面的例子中看到我们使用vm模块对eval有一个简单的包装,可以直接 使用$async方法来替换以前的写法。从打印信息中,你很容易看出访问 不到msg这个参数。麻烦请注意一下调用script.runInNewContext()方法 时传入了一个sandbox对象,这相当于往代码运行环境中添加上下文参数。 如果sanbox这个参数不传递,运行上端代码会报ReferenceError: Wind is not defined的错误。这就是eval为什么无法包装的原因。

如果你的代码不需要依赖上下文你可以用上述方法包装,例如这样:

var Wind = require("wind");

var vm = require("vm");
var sandbox = {
      Wind: Wind,
      console:console
};

function $async(fun){
    var script = vm.createScript(Wind.compile("async", fun));
    return script.runInNewContext(sandbox);
}

var fib = $async(function () {

    $await(Wind.Async.sleep(1000));
    console.log(0);
    
    $await(Wind.Async.sleep(1000));
    console.log(1);

    var a = 0, current = 1;
    while (true) {
        var b = a;
        a = current;
        current = a + b;

        $await(Wind.Async.sleep(1000));
        console.log(current);
    }
});

fib().start();

Wind.js很重很慢不适合前端

Wind.js基础组件及异步运行库共计4K大小(Minified + GZipped), Wind.js完全不会给前端带来负担,给你带来顺畅舒服的异步编程体验。

生成的代码看不懂,难以调试

Wind.js生产的代码也完全是Javascript代码,你无需为调试担忧。 下面是一个例子,我相信你很容易就可以看懂。

// Original: 
function () {

    $await(Wind.Async.sleep(1000));
    console.log(0);
    
    $await(Wind.Async.sleep(1000));
    console.log(1);

    var a = 0, current = 1;
    while (true) {
        var b = a;
        a = current;
        current = a + b;

        $await(Wind.Async.sleep(1000));
        console.log(current);
    }
}

// Windified: 
/* async << function () { */     (function () {
                                     var _builder_$0 = Wind.builders["async"];
                                     return _builder_$0.Start(this,
                                         _builder_$0.Delay(function () {
/*     $await(Wind.Async.sleep(1000)); */    return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/*     console.log(0); */                        console.log(0);
/*     $await(Wind.Async.sleep(1000)); */        return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/*     console.log(1); */                            console.log(1);
/*     var a = 0, current = 1; */                    var a = 0, current = 1;
                                                     return _builder_$0.While(function () {
/*     while (true) { */                                 return true;
                                                     },
                                                         _builder_$0.Delay(function () {
/*         var b = a; */                                     var b = a;
/*         a = current; */                                   a = current;
/*         current = a + b; */                               current = a + b;
/*         $await(Wind.Async.sleep(1000)); */                return _builder_$0.Bind(Wind.Async.sleep(1000), function () {
/*         console.log(current); */                              console.log(current);
                                                                 return _builder_$0.Normal();
                                                             });
                                                         })
/*     } */                                          );
                                                 });
                                             });
                                         })
                                     );
/* } */                          })

eval性能方面会有问题

有童鞋提出这方面的问题,但不知道提供什么样子的测试才能令人信服,从而消除疑虑,放心大胆的使用Wind.js。 这个问题还在收集整理中…

写在最后

在ADC被老赵的执着打动了,支持老赵从文档开始吧。 如果你还有对Wind.js的任何疑虑都可以留言,这个文档的目的就是消除你对Wind.js的疑虑。 原帖地址,会不断更新:这里

20 回复

呵呵,在ADC,吸引最多人的一次演讲确实是老赵的。

多谢支持!

在9月份的沪JS大会上我会想谈Jscex是怎么支持调试的,以及一些JavaScript调试方面一些不太被人关注的地方。接下来一段时间Jscex会有一系列增强调试的功能,说Jscex不容易调试的同学不妨关注一下。

希望有一個jscex的性能測試。

@byvoid 怎么对Jscex的怀疑又到性能上了,很无聊啊。Jscex从来就不是一个会影响性能的东西,你要怎么测试?

@jeffz 我只是心存疑慮啊,不測試怎麼能證明不會影響性能呢?

@byvoid 估计是怀疑eval会影响效率吧。。。。

@zxc122333 eval不会带来效率问题吧!有空搞个专门的测试,你可以把你担心哪个地方性能有问题告诉一下。

@zxc122333 从eval的使用方式就该知道不会影响性能,最后生产环境都不会出现eval……

@byvoid 首先nodejs不是用来写计算密集型应用的,一个IO就打倒千万次方法调用,其次Jscex从理论上说就不会降低性能……你说说你要什么样的测试吧……

弱弱的问下,这个与setTimeout(function(){},mil) 的差别有多大。

sleep吗?没差别,sleep内部就是封装了setTimeout

担心eval性能方面会有问题的童鞋,可以提出你的担心纠结的情境

老赵,你可以试着结合一些常用的异步场景,比如mongodb数据库访问,或者异步文件读写做一些压力测试数据,比较wind.js和原生的异步代码性能差别有多大。

意义何在啊,Wind.js又不是搞性能的,纯JS代码转换而已,自动帮你生成回调罢了。

一直有在关注Wind.js, 不过暂时没有应用到.

有个建议, 觉得官方的示例, 太枯燥了,很容易把初学者吓到. 就一个冒泡排序有点孤单, 可以再做几个类似之前blog上改写nodeclub那样的入门教程.

PS: http://windjs.org/cn/docs/async/samples/browser/sorting-animations/ 底部的链接错了.

@jeffz 因为用node.js的大部分都是考虑大并发的情况下,我们公司现在就用node.js做了几个项目都是这样的情况,比如一些对内的api查询接口,wind.js不知道性能损失会有多少,可能我个人比较关注这些吧

@snoopy 如果你了解Wind.js就会知道它不会造成性能损失啊,如果不了解你也不会用是不是……所以我一直觉得做性能测试就是个伪命题……

多谢,一会儿我去改一下。

@jeffz 虽然意义不大, 不过总可以用来吸引一些入门者吧,呵呵.

@atian25 把入门读者吸引歪了没有意义啊……

回到顶部