Reactive Extensions (Rx) 现已开源


[原文发表地址]  Reactive Extensions (Rx) is now Open Source

[原文发表时间]  November 6, 2012 9:24 PM

上次我和Erik Meijer一起制作有关.Net Reactive Extensions(Rx)的播客已有好几年了。从那个时候起,成千上万的人开始尽情在项目中使用Rx,并且很多开源项目如ReactiveUI(也可以在播客上看到)出现了。甚至Windows适用的GitHub也使用了Reactive Extensions。实际上,GitHub在Windows产品中大量使用了Rx。我在GitHub的一位朋友Paul说他非常喜欢这个模式,他们研发了一个Mac版本!

Windows适用的GitHub几乎对所有事情都使用Reactive Extensions,包括网络请求,UI事件,子进程管理(git.exe)。通过使用RxReactiveUI,我们已经编写了一个快速,几乎100%异步,响应迅速的应用,同时还有100%确定,可靠的单元测试。GitHub的桌面开发人员非常爱Rx,甚至Mac团队创建了他们自己的RxReactiveUI版本,被称为ReactiveCocoa,现在已经在Mac使用,以获得类似的好处。

——Paul BettsGitHub

今天,微软开源技术宣布Reactive Extensions开源的消息!你可以从https://rx.codeplex.com在Codeplex上使用git获取代码。你将无法抗拒这趟开源列车!祝贺这个伟大的团队!

这里包含了许多东西,因此热情已被点燃!这不仅有Rx.Net,还有C++库,以及JavaScript的RxJS!现在每个人都可以使用IObservable<T>和IObServer<T>玩弄它。

  • Reactive Extensions:

    • Rx.Net:Reactive Extensions(Rx)是一个实现异步和基于事件的程序的库,它使用了可察觉的序列和LINQ样式的查询运算符。
    • RxJS:JavaScript的Reactive Extensions(RxJS)是一个在JavaScript中实现异步和基于事件的程序的库,它使用了可察觉的序列和LINQ样式的查询运算符,它可以用于浏览器和Node.js。

    • Rx++:Native的 Reactive Extensions(RxC)是一个在C和C++中实现异步和基于事件的程序的库,它使用了可察觉的序列和LINQ样式的查询运算符。

  • Interactive Extensions

    • Ix:Interactive Extensions(Ix)是一个.Net库,它扩展LINQ to Object,提供许多在Rx可用的操作符,但是面向IEnumerable<T>。
    • IxJS:JavaScript中的LINQ to Object开发和Interactive Extensions (Ix)
    • Ix++:C++中供Native开发人员使用LINQ

一个学习有关为什么Rx有用的很好的方法是点击Rx Koan的工程或者阅读介绍Rx的在线电子书

为什么我认为Rx很重要?它是一个在事件流上实现异步操作的方式。而不是连接点击事件和用事件处理程序管理所有事件的状态,你可以有效地用LINQ查询一个事件的无限流。你可以声明式的排序事件……不用标记,没有状态机。

例如,这里用鼠标按键和鼠标移动事件创建了一个拖拽事件(已设计好):

IObservable<Event<MouseEventArgs>> draggingEvent =

     from mouseLeftDownEvent in control.GetMouseLeftDown()

     from mouseMoveEvent in control.GetMouseMove().Until(control.GetMouseLeftUp())

     select mouseMoveEvent;

更胜一筹的是,Rx让它更容易(或者更可能)地创建基于事件的异步测试,像来自Jafar Husain的此

Rating rating = new Rating();

IObservable<Unit> test =                             // Unit is an object that represents null.

    ObservableExtensions

        .DoAsync(() => TestPanel.Children.Add(rating))

        .WaitFor(TestPanel.GetLayoutUpdated())     // Extension method GetLayoutUpdated converts the event to observable        

        .DoAsync(() => rating.Value = 1.0)        // Calls the Ignite EnqueueCallback method        

        .WaitFor(                                 // waits for an observable to raise before going on

            // listen to all the actual value change events and filters them until ActualValue reaches Value            

            rating                                      

            .GetActualValueChanged()        // extension method that converts ActualValueChanged event to IObservable

            .SkipWhile(actualValueChangedEvent => actualValueChangedEvent.EventArgs.NewValue != rating.Value))

        // check to make sure the actual value of the rating item is set appropriately now that the animation has completed

        .Assert(() => rating.GetRatingItems().Last().ActualValue == 1.0) // crawls the expression tree and makes a call to the appropriate Assert method

 

 Test.Subscribe(() => TestPanel.Children.Remove(rating));    //run the test and clean up at the end.

这是一个很棒的时间相关的操作,让你随着时间移动模拟事件。注意Buffer和Subscribe的调用

var myInbox = EndlessBarrageOfEmail().ToObservable();

 

 // Instead of making you wait 5 minutes, we will just check every three seconds instead. 🙂

var getMailEveryThreeSeconds = myInbox.Buffer(TimeSpan.FromSeconds(3)); //  Was .BufferWithTime(... 

 

getMailEveryThreeSeconds.Subscribe(emails =>

{

    Console.WriteLine("You've got {0} new messages!  Here they are!", emails.Count());

    foreach (var email in emails)

    {

        Console.WriteLine("> {0}", email);

    }

    Console.WriteLine();

});

你可以使用await和async就像这个例子一样,在5秒后返回数字42:

static async void button_Click()

{

    int x =  await Observable.Return(42).Delay(TimeSpan.FromSeconds(5));

    // x with value 42 is returned after 5 seconds

    label.Text = x.ToString();

}

我在这里只是为您展示了我所喜欢的部分,但是一个人也可以轻松地在大学讲上10周有关Rx的课程,但我还只是一个初学者。

这里有更多Rx资源,请点击查看。祝贺这个伟大的团队在开源方面做出的贡献!

Comments (0)

Skip to main content