Giter Club home page Giter Club logo

wind's Introduction

What's Wind.js

Wind.js is an advanced library which enable us to control flow with plain JavaScript for asynchronous programming (and more) without additional pre-compiling steps.

Documentation

Check out windjs.org for guides and documentation.

License

(The BSD License)

Copyright 2012 (c) Jeffrey Zhao [email protected]
Based on UglifyJS (https://github.com/mishoo/UglifyJS).

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above
      copyright notice, this list of conditions and the following
      disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials
      provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

wind's People

Contributors

imzc avatar jeffreyzhao avatar liunian avatar snda-chengshaofei avatar thorn0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wind's Issues

binding object and $await

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 ?

The missing libs of seq in samples.

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.

about task cancellation

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?

jit 的bug?

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);
            }
        },

The "funding" page

Describe the information about "Jscex founding" like:

  1. Monthly incoming
  2. History cost
  3. Increasing numbers as GMail's storage size

关于for和if的} 后加分号的奇怪现象

发现一个比较奇怪的现象。由于我用了一个小工具把以前是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 () {
};

Compile configuration

Add an optional config parameter to compile method, support some parameters:

  • root - "Wind" by default
  • noSourceUrl - false by default
  • name

赵兄

偶然发现这个好东东. 下下来试用.

Firefox 和 Chrome都可以正常工作. 但 IE7下不报错也没反应是怎么回事.

求教 has no method 'start' 的错误是啥问题

求教哪里出错了


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)

dependency of variable name "Jscex"

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)

Support multiple loaders separately

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.

Wind.compileBlock method for compile a whole code block

Usage:

Jscex.compileBlock(options /* or name */, function () {
    /* code block */
});

The name would be used in "//@ sourceURL".

Assign a better name for generated function:

  • Use the function name if it's not a anonymous method.
  • Use the Jason name if it's created like this: myFunc: eval(...)
  • Use the variable name if it's assigned to a variable: var myFunc = eval(...) or myFunc = eval(...)
  • Use the field name if it's assigned to a field name: a.myFunc = eval(...)

Restructure the async samples

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.

$await is not defined

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);
}

关于代码错误的准确位置的问题

老赵,您好:
我有一个比较复杂的应用正在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)

Improve sorting animation sample

Target:

  • Shows user the correct message and stop further operation if the browser doesn't support canvas.
  • Choose quick sort by default.
  • Can be included in an iframe.

Reduce the module number

Combine "jscex-parser" and "jscex-jit" into a single "jscex-compiler".

Combine "jscex-async" and "jscex-async-powerpack" into a single "jscex-async".

写给 Jscex 的一些建议

抱歉呀,今天才仔细阅读了一遍 Jscex 的文档,按照阅读顺序,提供一些建议:

首页

  1. jscex.info 这域名,是因为 jscex.org 被人抢占了么?如果 org 在老赵手上,建议用 org,这是开源组织的标配。另外,建议首页默认是中文,右上角给个英文版的链接就好。毕竟 Jscex 目前主要是想在大陆推广吧?国际化可以缓一缓。我们可以先尝试下先国内后国外的战略,发展**家包围发达国家。能成的话,也是一种新气象,不然国人老是以为国外的月亮更圆,我们得让同胞们看看我们自身的实力,扭转大众的一些误区。
  2. Jscex 专项拨款挺好的,但缺乏明确的游戏规则。建议可以将参与方式、奖品规则写一篇博客详细介绍下,这样能更让诚意更具诚意,说不定哪位心头一热,就会开始给社区做贡献了。虽然奖品不是目的,但明确的游戏规则可以让运营更实际有效。
  3. “能够在任意支持ECMAScript 3的执行引擎里使用”,这句话建议去掉,容易给普通用户造成误解,比如:什么是 ECMAScript 3?怎么只支持 ECMAScript 3,难道不支持 ECMAScript 5 吗?可以考虑改成:能够在任意主流 JavaScript 引擎中使用。至于什么是主流 JS 引擎,知者自知,不必去解释,除非真有人问题(一般不会有人问)。
  4. 冒泡排序,对于计算机科班出身的程序员来说,不是问题。但 Jscex 如果想推广给更多前端程序员用,则写一小段文字或给出参考链接来解释下什么是冒泡排序还是有必要的,比如 NCZ 写过一篇 Computer science in JavaScript: Bubble sort。把用户当白痴,很重要很重要。国内技术圈,比我们想象中的浮躁很多。
  5. 冒泡排序这个例子,对于 Jscex 来说,核心还是动画的实现。我建议直接换成一个简单的 “Hello, World” 的文字飘入动画就好。今晚有时间的话,我来基于 seajs 的 plugin-jscex 做一个。这样应该能更亲民一些。冒泡排序可以作为进阶中的案例。
  6. “增加交换和比较操作的耗时,因为排序算法的性能主要取决于交换和比较操作的次数多少。” 这个说得不清楚,在这个例子里,增加耗时的目的,我觉得跟性能无关,而是为了让动画看起来不那么太快。建议改成:“增加交换和比较操作的耗时,这样在动画演示时能比较容易看清楚。”
  7. eval(Jscex.compile("async", function (x, y) { 这种写法,对入门者来说还是比较逆天的。打算在 seajs/plugin-jscex 里,把这技术实现细节隐藏掉。老赵等我的插件。
  8. $await(Jscex.Async.sleep(10)) 的写法,感觉也不够简洁。感觉也是将内部的实现暴露了出来。建议可以为外部用户提供一个 shortcut: $await(10). 其实我还有一个疑问:为什么要用 await ? 而不是更直白的 wait 或 sleep ?

开发指南

  1. 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 版本交给那些对性能有追求的高级使用者去玩。

  1. 构造器基础模块究竟是干嘛的?文档里没有解释什么是构造器,以及什么时候需要自己构建构造器?看得不是很明白。这应该是高级用户才会去玩的吧?估计要看源码才知道如何去写。在文档里,如果某个内容说不清楚,建议不如先隐藏掉。
  2. 包引入这文档,动态依赖和静态依赖貌似写反了。静态依赖是需要手动自己去写依赖,动态依赖是指可以动态自动加载。还是我理解错了?
  3. async 居然还有一个 powerpack, 建议如果不是真的 power 到几十K的体积,建议就放到默认的 async 里。
  4. 感觉太多内部细节暴露给了使用者,感觉不是很妥当。是否可以在现有 API 的基础上,再包装出一层更傻瓜的高级 API ?比如上面提到了一些:
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. 如果可行就太好了。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.