jeffreyzhao / wind Goto Github PK
View Code? Open in Web Editor NEWAsynchronous flow control in JavaScript, with JavaScript.
Home Page: http://windjs.org/
Asynchronous flow control in JavaScript, with JavaScript.
Home Page: http://windjs.org/
Rename everything "Jscex" to "Wind". "jscexc" should also be renamed to "windc".
能否将 Jscex.compile("async", function (){})
改为更简单的接口,每次都输 Jscex.compile("async")
很难受, 能否改为 Jscex.compileAsync( function () { } )
或者其他类似的更简便的接口.
The published version in bin
folder needs to be versioned.
http.getAsync = function(options) {
return Task.create(function (t) {
http.get(options, function(res) {
t.complete("success", res);
}).on("error", function(ex) {
t.complete("failure", ex);
});
});
};
var downloadAsync = eval(Jscex.compile("async", function (_url) {
var options = {
host: url.parse(_url).host,
port: 80,
path: url.parse(_url).pathname,
headers: headers
};
// console.log(options);
var baseDir = './public/';
var filename = url.parse(_url).pathname.split('/').pop();
var r = $await(http.getAsync(options));
console.log(r.statusCode);
r.pipe(fs.createWriteStream(path.join(baseDir, filename)));
r.on("end", function() {
console.log(filename + ' end!');
});
}));
var x = 0;
var batchDownloadAsync = eval(Jscex.compile("async", function() {
for (; pages >= 1; pages--) {
var _url = util.format(baseUrl, pages);
var options = {
host: url.parse(_url).host,
port: 80,
path: url.parse(_url).pathname,
headers: headers
};
var resp = $await(http.getAsync(options));
if (resp.statusCode !== 200) {
console.log('failed to get ' + _url);
process.exit();
}
var stack = '';
resp.on('data', function(chunk){
stack += chunk;
});
resp.on('end', function() {
var fileUrl = $(stack).find('#copy_file').val();
// if (fileUrl && fileUrl.indexOf('.mp3') !== -1) {
// x++;
// console.log(x + ' *********');
// downloadAsync(fileUrl).start();
// }
// $await(downloadAsync(fileUrl)); <- 这里的$await没法识别
downloadAsync(fileUrl).start(); // <- 换成这个就可以
});
x++;
if (x > 0 && x % 2 === 0) {
console.log(x + ' ###############');
$await(Jscex.Async.sleep(1000 * 60 * 4));
}
}
}));
try {
batchDownloadAsync().start();
} catch (ex) {
console.log(ex);
}
I feel that using a cancellation token to cancel a task makes code more complex, since we have the burden to manage task concellation tokens. I prefer adding two methods cancel() and is_cancelling to task object, and do not throw exception while cancelling (sometimes cancel is not an exception or error, it's a normal opeation, so throw exceptions might be unexpected).
For example, in an async task, I wish to write:
var foo_task = eval(Jscex.compile("async", functoin() {
var task1 = Task1(), task2 = Task2();
task1.start(); task2.start();
while( true ) {
$await(some_kind_of_event_for_example_a_timer());
/* it might be convenient to use $task as the reference to the current task?
thus I can write:
if( $task.is_cancelling() )
*/
if( this_task.is_cancelling() )
{
task1.cancel(); task2.cancel();
/*
task1 and task2 check the cancelling and then quit
*/
$await(task1, task2);
break;
}
}
}));
I think this is simple and clean, what's your opinion?
Describe the information about "Jscex founding" like:
We can use temp ids in "whenAll" and "whenAny".
偶然发现这个好东东. 下下来试用.
Firefox 和 Chrome都可以正常工作. 但 IE7下不报错也没反应是怎么回事.
发现一个比较奇怪的现象。由于我用了一个小工具把以前是oracle存储过程的代码直接转换成Javascript用于NodeJs上跑,会自动在for{}循环后面和在if的最后的大括号}后面加上分号,如果这代码双放在jscex的异步代码中,就会报一些奇怪的错误,去掉后就没问题了。
我有一段代码,是从redis里获取出来keys后,再循环把key的值取出来,代码如下:
1、我用forEach作的话:
keys.forEach(function (key, i) {
var row = $await(cache.oper('hgetall', key));
});
编译后运行时会报:$await is not defined ,其实时编译后并没有编码这段代码。
2、我用 for (var key in keys)
,编译时就报:
for (var i = 0; i < statements.length; i++) {
TypeError: Cannot read property 'length' of undefined
3、if后面加上分号也报这种类似的错误。把分号去掉就不报错了。
if () {
};
Separate the samples by environment (browsers and Node.js) and move incubation samples into another folder.
For Node.js samples, create a "wind.js" file to import all the modules, just like importing the single package from npm.
Shouldn't print warnings, use uncaughtError
event instead.
Using the metadata in module directly.
Add to NuGet packages.
Now all the loader support are built into core and each module, which increase the size of scripts and make it harder to write modules.
We need a better way to support multiple loaders separately.
Is it possible to use other variable name instead of "Jscex" while importing jscex module in nodejs? For example:
var asynco = require("jscex");
require("jscex-jit").init(asynco);
require("jscex-async").init(asynco);
require("jscex-async-powerpack").init(asynco);
asynco.logger.level = 3;
var async_fn = eval(asynco.compile("async", function() {
console.log("hello async");
}));
async_fn().start();
The code above fails with error:
undefined:2
var _builder_$0 = Jscex.builders["async"];
^
ReferenceError: Jscex is not defined
at eval at <anonymous> (W:\a.js:9:28)
at Object.<anonymous> (W:\a.js:13:1)
at Module._compile (module.js:446:26)
at Object..js (module.js:464:10)
at Module.load (module.js:353:31)
at Function._load (module.js:311:12)
at Array.0 (module.js:484:10)
at EventEmitter._tickCallback (node.js:190:38)
The usage would become:
var Wind = require("wind");
Refer to the helpers in underscore.js.
Implement sorting algorithms with O(1) memory Refer to the page in Wikipedia.
Target:
WinRT uses CommonJS Promises/A Proposal. Jscex already has a draft winrt-jscex module, so it should be very easy to migrate the code.
I'm trying to use jscex in an animation lib, this lib rely heavily on setInterval and clearInterval, I found that jscex compile await/sleep methods to setTimeout instead of setInterval, this there an equivalent jscex method of clearInterval?
an example of clearInterval
Targets:
Keep the old jscex.org website for 0.6.5 information.
It would be excellent if you can provide any info about how to do that.
老赵,您好:
我有一个比较复杂的应用正在nodeJs上使用Jscex开发,跟数据库和缓存NOSQL数据库的交互比较多。当代码出现异常时,根据错误的信息得不到出错的行号,而是指向异步函数的开始位置,我想这应该是在编译时eval报的错,如果要得到准确的行号和module文件名,有什么招数么?
谢了!
如下:文件findCust.js代码有个位置的函数isNull未定义,而这个文件又引用几个别的库,类似出现的异常找起来很不方便:
执行出错:ReferenceError: isNull is not defined
Trace:
at [object Object]. (eval at (/usr/local/future/ctrl/findCust.js:69:28))
at /usr/local/future/node_modules/jscex-async/jscex-builderbase.js:231:64
at Object. (/usr/local/future/node_modules/jscex-async/jscex-async.js:201:33)
at Object._notify (/usr/local/future/node_modules/jscex-async/jscex-async.js:139:34)
at Object.complete (/usr/local/future/node_modules/jscex-async/jscex-async.js:126:22)
at /usr/local/future/node_modules/jscex-async/jscex-async.js:187:31
at /usr/local/future/node_modules/jscex-async/jscex-builderbase.js:162:29
at /usr/local/future/node_modules/jscex-async/jscex-builderbase.js:242:41
at Object. (/usr/local/future/node_modules/jscex-async/jscex-async.js:201:33)
at Object._notify (/usr/local/future/node_modules/jscex-async/jscex-async.js:139:34)
For example, property accessor for result
and error
.
Add an optional config
parameter to compile method, support some parameters:
root
- "Wind"
by defaultnoSourceUrl
- false
by defaultname
Usage:
Jscex.compileBlock(options /* or name */, function () {
/* code block */
});
The name would be used in "//@ sourceURL".
Assign a better name for generated function:
myFunc: eval(...)
var myFunc = eval(...)
or myFunc = eval(...)
a.myFunc = eval(...)
fromPromise (Promise/A), toCallback, toStandard
Targets:
Now the code for module loading is duplicated for each modules, consolidate them in the basic module and used in others.
Support both Windows and *nix.
Just a simple CRUD sample with a list style display, handling exception properly.
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 ?
Invistigate Hightlight.js and make simple changes.
Use repository.jscex.info domain to browse the lastest code of Jscex, which could be used in docs.
From @audreyt:@jeffz_cn 今天剛看到,正在試用,很有意思。AOT 生成的代碼似乎可以考慮用 https://github.com/mozilla/source-map 生成源碼對映表,以便偵錯。
AOT would be failed with || and && operators, a simple fix to jscex.js is sufficient.
求教哪里出错了
require('../lib/jscex.mysql').jscexify(db);
var testAsync = eval(Jscex.compile("async",function(){
sql = 'select * from '+opt.db_name+'.'+tb_name+' limit 10';
var ret = $await(db.queryAsync(sql));
}))
testAsync.start();
报错内容如下
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Object function () {
var _builder_$0 = Jscex.builders["async"];
return _builder_$0.Start(this,
_builder_$0.Delay(function () {
/* sql = "select * from " + opt.db_name + "." + tb_name + " limit 10"; */ sql = "select * from " + opt.db_name + "." + tb_name + " limit 10";
/* var ret = $await(db.queryAsync(sql)); */ return _builder_$0.Bind(db.queryAsync(sql), function (ret) {
return _builder_$0.Normal();
});
})
);
/* } */ } has no method 'start'
at Object. (/Users/chatfeed/webroot/SGRPG/ServerCode/server/nodejs/logic/test.js:50:11)
at Module._compile (module.js:441:26)
at Object..js (module.js:459:10)
at Module.load (module.js:348:31)
at Function._load (module.js:308:12)
at Array.0 (module.js:479:10)
at EventEmitter._tickCallback (node.js:192:40)
jscex 是我用过的最好的javascript的库之一,现在没有它日子已经没法过了。在使用过程中发现一个jit的问题:delete obj.key 会被翻译成 deleteobj.key, 中间缺少一个空格。我做了一点修改不知是否正确:
jscex-jit.js中,this._both(op) 改成 this._both(op + " ");
"unary-prefix": function (ast) {
var op = ast[1];
var item = ast[2];
this._both(op + " ");
if (op == "typeof") {
this._both("(")._visitRaw(item)._both(")");
} else {
this._visitRaw(item);
}
},
Combine "jscex-parser" and "jscex-jit" into a single "jscex-compiler".
Combine "jscex-async" and "jscex-async-powerpack" into a single "jscex-async".
Also create a new "jscex" repository and redirect to "wind".
From the talks project.
抱歉呀,今天才仔细阅读了一遍 Jscex 的文档,按照阅读顺序,提供一些建议:
jscex.info
这域名,是因为 jscex.org
被人抢占了么?如果 org 在老赵手上,建议用 org,这是开源组织的标配。另外,建议首页默认是中文,右上角给个英文版的链接就好。毕竟 Jscex 目前主要是想在大陆推广吧?国际化可以缓一缓。我们可以先尝试下先国内后国外的战略,发展**家包围发达国家。能成的话,也是一种新气象,不然国人老是以为国外的月亮更圆,我们得让同胞们看看我们自身的实力,扭转大众的一些误区。eval(Jscex.compile("async", function (x, y) {
这种写法,对入门者来说还是比较逆天的。打算在 seajs/plugin-jscex 里,把这技术实现细节隐藏掉。老赵等我的插件。$await(Jscex.Async.sleep(10))
的写法,感觉也不够简洁。感觉也是将内部的实现暴露了出来。建议可以为外部用户提供一个 shortcut: $await(10)
. 其实我还有一个疑问:为什么要用 await ? 而不是更直白的 wait 或 sleep ?require("jscex-parser").init()
建议简化成 require("jscex-parser")
,init 内置掉。我还是期望对使用者来说,不要去理解什么是核心组件,什么是 parser,只要简简单单 var Jscex = require(jscex)
就万事大吉了。jit 可以让用户按需引入。或者变成:require('jscex') // 用于开发时,含 core、buildbase, async, parser 和 jit
require('jscex-runtime') // 用户上线后,只含 core, buildbase, async
这样也方便用户部署,而且大部分用户,用开发时的就满足了需求,runtime 版本交给那些对性能有追求的高级使用者去玩。
require('jscex') // <-- 80% 的用户,只要这一句就好了,然后全局就有了 Jscex 和 $await 等变量
$await(10) // <-- 等价 $await(Jscex.Async.sleep(10))
这个文档入口,在开发指南里居然没有。我花了好长时间才从首页找到一个入口,有点囧。
$await指令的使用形式便是普通的方法调用,但事实上在上下文中并没有这个方法。它的作用与eval(Jscex.compile("async", …))一样,仅仅是个占位符,让Jscex知道在这个地方需要进行“特殊处理”。
这段话是否有误?能理解 $await
是个占位符,eval(Jscex.compile("async", …))
怎么也成了占位符?我没看 jscex 的源码,直觉上,Jscex.compile("async", fn)
是一个真实的普通函数,这个函数执行时,会分析第二个参数 fn 中的 $await
等占位符,然后进行一系列操作,结果是一段编译后的代码,最后交给 eval 去在当前 context 上执行。我理解是否有误?
这个并发的例子:
var queryUserTask = queryUserAsync(userId);
// 手动启动queryUserAsync任务,start方法调用将立即返回。
queryUserTask.start();
var items = $await(queryItemsAsync(userId));
var user = $await(queryUserTask); // 等待之前的任务完成
感觉理解起来还是有点绕。不如 async 等类库提供的 api 方便,比如类似:
async. parallel([queryUserAsync(userId), queryItems(userId)], function(users, items) {
// do sth
})
async 类库不反对异步回调,只是将回调套回调的写法变得更简单清晰。文档读到这里,Jscex 对我来说,貌似只有 $await
让我觉得非常诱人,难以舍弃-.-
Event 这个例子让人有点小兴奋了,居然还可以这样用。我前面有些地方误解 Jscex 了,误解的文字也就不去修改了,保留一份阅读文档过程中的真实记录。
我喜欢这个:
return $await(Task.whenAll({
user: queryUserAsync(userId),
items: queryItemsAsync(userId)
}));
比 async 类库强太多了。依旧期待是否在包装出一个高级 API,比如:
return $await.parallel({
user: queryUserAsync(userId),
items: queryItemsAsync(userId)
}));
CancellationToken
又是高级用户内容了,这被普通用户看见,会有心理障碍的-.-
这取消模型还是得赞下,设计得挺棒的。
下面的貌似都是高级内容,我决定需要的时候再看,这份建议就写到这。
最后说个总体感觉,$await
魅力无穷,但需要通过 eval(Jscex.compile...)
或 Task.create
来创建 AsyncTask 给 $await 调用,感觉对普通用户有难度,需要理解的东西比较多,写的时候要换一些思维去想。
$await
是更自然的异步流程控制,但感觉 task 不是很自然,没有传统的 callback 容易理解。
是否可以将 Task 隐藏掉?比如首页的例子如果能像下面这样写就帅呆啦:
function compare(x, y) {
$await(10); // 暂停10毫秒
return x - y;
}
function swap(a, i, j) {
$await(20); // 暂停20毫秒
var t = a[i]; a[i] = a[j]; a[j] = t;
paint(a); // 重绘数组
}
function bubbleSortAsync(array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
// 异步比较元素
var r = $await(compare(array[y], array[y + 1])); // 如果这里也可以把 $await 省略掉就更帅啦
// 异步交换元素
if (r > 0) $await(swap(array, y, y + 1));
}
}
}
上面的代码,是在某一个文件里,比如 xx.js,这在 node 或 commonjs 里,都是一个模块,意味着我们可以在模块编译时,做点手脚,比如对于 NodeJS 环境,可以在 Module._compile 调用时,自动将 eval(Jscex.compile...)
加上。
SeaJS 的 plugin-jscex 我就是想这么干的,让开发时用户可以直接写成:
define(function(require, exports, module) {
function compare(x, y) {
$await(10); // 暂停10毫秒
return x - y;
}
function swap(a, i, j) {
$await(20); // 暂停20毫秒
var t = a[i]; a[i] = a[j]; a[j] = t;
paint(a); // 重绘数组
}
function bubbleSortAsync(array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
// 异步比较元素
var r = $await(compare(array[y], array[y + 1])); // 如果这里也可以把 $await 省略掉就更帅啦
// 异步交换元素
if (r > 0) $await(swap(array, y, y + 1));
}
}
}
})
然后我在模块编译时,通过 plugin-jscex, 将上面的代价等价成:
define(eval(Jscex.compile('async', function(require, exports, module) {
function compare(x, y) {
$await(10); // 暂停10毫秒
return x - y;
}
function swap(a, i, j) {
$await(20); // 暂停20毫秒
var t = a[i]; a[i] = a[j]; a[j] = t;
paint(a); // 重绘数组
}
function bubbleSortAsync(array) {
for (var x = 0; x < array.length; x++) {
for (var y = 0; y < array.length - x; y++) {
// 异步比较元素
var r = $await(compare(array[y], array[y + 1])); // 如果这里也可以把 $await 省略掉就更帅啦
// 异步交换元素
if (r > 0) $await(swap(array, y, y + 1));
}
}
}
})))
老赵看看这样是否可行?等你确定后我再来折腾 plugin-jscex. 如果可行就太好了。
Why not upload this amazing library to the NuGet gallery? :)
Just realized the sample seq missing a lib named uglifyjs-parser.js, not sure if anyone removed from master.
And require "../../src/jscex.builderBase.js" in fib.html should be "../../src/jscex-builderbase.js" now. Thanks Jeffrey for hard working this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.