SkillAgentSearch skills...

Bacon.js

Functional reactive programming library for TypeScript and JavaScript

Install / Use

/learn @baconjs/Bacon.js
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Bacon.js

<img src="https://raw.github.com/baconjs/bacon.js/master/logo.png" align="right" width="300px" />

A functional reactive programming lib for TypeScript JavaScript, written in TypeScript.

Turns your event spaghetti into clean and declarative feng shui bacon, by switching from imperative to functional. It's like replacing nested for-loops with functional programming concepts like map and filter. Stop working on individual events and work with event streams instead. Combine your data with merge and combine. Then switch to the heavier weapons and wield flatMap and combineTemplate like a boss.

Here's the stuff.

Build Status BrowserStack Status NPM version Dependency Status devDependency Status

Install and Usage

Typescript

Bacon.js starting from version 3.0 is a Typescript library so you won't need any external types. Just Install using npm.

npm install baconjs

Then you can

import { EventStream, once } from "baconjs"

let s: EventStream<string> = once("hello")
s.log()

As you can see, the global methods, such as once are imported separately.

Check out the new API Documentation, that's now generated using Typedoc from the Typescript source code.

Modern ES6 Browser, Node.js v.12+

You can directly import Bacon.js as single aggregated ES6 module.

import * as Bacon from 'node_modules/baconjs/dist/Bacon.mjs';
Bacon.once("hello").log();

NPM, CommonJS, Node.js

If you're on to CommonJS (node.js, webpack or similar) you can install Bacon using npm.

npm install baconjs

Try it like this:

node
Bacon=require("baconjs")
Bacon.once("hello").log()

The global methods, such as once are available in the Bacon object.

Bower

For bower users:

bower install bacon

CDN / Script Tags

Both minified and unminified versions available on cdnjs.

So you can also include Bacon.js using

<script src="https://cdnjs.cloudflare.com/ajax/libs/bacon.js/2.0.9/Bacon.js"></script>
<script>
Bacon.once("hello").log()
</script>

AMD / require.js

Bacon.js is an UMD module so it should work with AMD/require.js too. Not tested lately though.

Github

Prefer to drink from the firehose? Download from Github master.

Intro

The idea of Functional Reactive Programming is quite well described by Conal Elliot at Stack Overflow.

Bacon.js is a library for functional reactive programming. Or let's say it's a library for working with events in EventStreams and dynamic values (which are called Properties in Bacon.js).

You can wrap an event source, say "mouse clicks on a DOM element" into an EventStream by saying

let $ = (selector) => document.querySelector(selector) 
var clickE = Bacon.fromEvent($("h1"), "click")

The $ helper function above could be replaced with, for instance, jQuery or Zepto.

Each EventStream represents a stream of events. It is an Observable, meaning that you can listen to events in the stream using, for instance, the onValue method with a callback. Like this:

clickE.onValue(() => alert("you clicked the h1 element") )

But you can do neater stuff too. The Bacon of Bacon.js is that you can transform, filter and combine these streams in a multitude of ways (see EventStream API). The methods map, filter, for example, are similar to same functions in functional list programming (like Underscore). So, if you say

let plusE = Bacon.fromEvent($("#plus"), "click").map(1)
let minusE = Bacon.fromEvent($("#minus"), "click").map(-1)
let bothE = plusE.merge(minusE)

.. you'll have a stream that will output the number 1 when the "plus" button is clicked and another stream outputting -1 when the "minus" button is clicked. The bothE stream will be a merged stream containing events from both the plus and minus streams. This allows you to subscribe to both streams with one handler:

bothE.onValue(val => { /* val will be 1 or -1 */ console.log(val) })

Note that you can also use the log method to log stream values to console:

bothE.log()

In addition to EventStreams, bacon.js has a thing called Property, that is almost like an EventStream, but has a "current value". So things that change and have a current state are Properties, while things that consist of discrete events are EventStreams. You could think mouse clicks as an EventStream and mouse cursor position as a Property. You can create Properties from an EventStream with scan or toProperty methods. So, let's say

let add = (x, y) => x + y
let counterP = bothE.scan(0, add)
counterP.onValue(sum => $("#sum").textContent = sum )

The counterP property will contain the sum of the values in the bothE stream, so it's practically a counter that can be increased and decreased using the plus and minus buttons. The scan method was used here to calculate the "current sum" of events in the bothE stream, by giving a "seed value" 0 and an "accumulator function" add. The scan method creates a property that starts with the given seed value and on each event in the source stream applies the accumulator function to the current property value and the new value from the stream.

Hiding and showing the result div depending on the content of the property value is equally straightforward

let hiddenIfZero = value => value == 0 ? "hidden" : "visible"
counterP.map(hiddenIfZero)
  .onValue(visibility => { $("#sum").style.visibility = visibility })

For an actual (though a bit outdated) tutorial, please check out my blog posts

API

Creating EventStreams and Properties

There's a multitude of methods for creating an EventStream from different sources, including the DOM, node callbacks and promises for example. See EventStream documentation.

Properties are usually created based on EventStreams. Some common ways are introduced in Property documentation.

Combining multiple streams and properties

You can combine the latest value from multple sources using combine, combineAsArray, combineWith or combineTemplate.

You can merge multiple streams into one using merge or mergeAll.

You can concat streams using [concat](http://baconjs.github.io/api3/classes/observable.html#c

Related Skills

View on GitHub
GitHub Stars6.5k
CategoryDevelopment
Updated7d ago
Forks329

Languages

TypeScript

Security Score

95/100

Audited on Mar 19, 2026

No findings