JeffreyZhao / wind

Asynchronous flow control in JavaScript, with JavaScript.
http://windjs.org/
1.54k stars 238 forks source link

在windjs的基础上封装像golang一样的并行编程接口(内有代码) api like golang (code attach) #78

Open bronze1man opened 11 years ago

bronze1man commented 11 years ago

想法

模仿golang的接口,可以把windjs的接口做的更加抽象,和正交... 既然windjs可以把异步转为同步,golang也有办法把同步转为异步,异步转成同步. 为什么不尝试提供golang的并行编程接口呢?

实现

golang 有2个接口和并行编程有关: 1.创建goroute(线程) 如: go func(ch chan<- bool) { for { sleep(10); ch <- true; }} (c) 这个windjs本身已经提供.简单封装就可以了. 2.channel数据类型 如: go func(ch chan<- bool) { for { sleep(10); ch <- true; }} (c) 先用异步回调接口实现channel对象,后用windjs的接口把异步转为同步.实现了同步接口下的channel对象.

可以改进的地方

1.创建goroute的方法可以省掉.start() 2.没有实现带buffer的channel... 3.函数嵌套问题(不明白函数调用规则...召唤文档)


<script src='wind-all-0.7.3.js'></script>
<script>
var a=2;
//new thread 建立新线程
function go(cb){
    return eval(Wind.compile('async',cb));
}
//channel exchange data 使用channel发送数据,或者同步两个线程的执行
//异步channel对象
function channel(){
    return {
        'read_cb':[],
        'write_cb':[],
        'data':[],
        'read':function(cb){
            this.read_cb.push(cb);
            if (this.write_cb.length>0){
                this.do();
            }
        },
        'write':function(data,cb){
            this.data.push(data);
            this.write_cb.push(cb);
            if (this.read_cb.length>0){
                this.do();
            }
        },
        'do':function(){
            var read_cb = this.read_cb.pop();
            var write_cb = this.write_cb.pop();
            var data = this.data.pop();
            read_cb(data);
            write_cb();
        }
    };
}
var c1=new channel();
//测试异步channel对象
function test1(){
    c1.read(function(data){console.log(data);});
    c1.read(function(data){console.log(data);});
    c1.read(function(data){console.log(data);});
    c1.write('data_on_channel',function(){console.log('write finish1')});
    c1.write('data_on_channel',function(){console.log('write finish2')});
    c1.write('data_on_channel',function(){console.log('write finish3')});
    c1.read(function(data){console.log(data);});
    c1.write('data_on_channel',function(){console.log('write finish4')});
}
//同步channel对象
function channelAsync(){
    var origin = new channel();
    origin.read = Wind.Async.Binding.fromCallback(origin.read);
    origin.write = Wind.Async.Binding.fromCallback(origin.write);
    return origin;
}

//使用样例1
function test2(){
    var c2=new channelAsync();
    var reader = go(function(c){
        $await(Wind.Async.sleep(1000));
        console.log('start read');
        recv_data = $await(c.read());
        console.log('end read recv:'+recv_data);
    })(c2).start();
    var writer = go(function(c){
        $await(Wind.Async.sleep(100));
        console.log('start write');
        $await(c.write('send_data'));
        console.log('end write');
    })(c2).start();

}

//使用样例2
function test3(){
    var c=new channelAsync();
    for (i=0;i<10;i++){
        go(function(c,i){
            $await(Wind.Async.sleep(Math.random()*1000 ));
            $await(c.write('1'));
            console.log('read finish'+i);
        })(c,i).start();
    }
    go(function(c){
    for (i=0;i<10;i++){
        $await(c.read());
    }
    })(c).start();
}

setTimeout(test1,1000);
setTimeout(test2,2000);
setTimeout(test3,4000);
</script>
bronze1man commented 11 years ago

然后我想试试复杂一点的情况,但是不知道如何用windjs完成它....到底哪些地方需要用$await呢? golang代码如下...

package main
import "fmt"
import "time"
//同步转换为异步
func setTimeout(cb func(),timeout int){
    go func(){
        time.Sleep( time.Duration(int64(timeout)*1e9));
        cb();
    }()
}
//异步转换为同步
func sleep(timeout int){
    c:=make(chan int);
    go func(){
        setTimeout(func(){
            c<-1
        },timeout)
    }()
    <-c
}
func main(){
    setTimeout(func(){
        fmt.Println("after time out");
    },1);
    fmt.Println("before sleep");
    sleep(2);
    fmt.Println("after sleep");
}