Convert Figma logo to code with AI

cujojs logomost

Ultra-high performance reactive programming

3,495
231
3,495
50

Top Related Projects

30,605

A reactive programming library for JavaScript

Observables for ECMAScript

2,375

An extremely intuitive, small, and fast functional reactive stream library for JavaScript

1,559

👜 A standard for JS callbacks that enables lightweight observables and iterables

Functional reactive programming library for TypeScript and JavaScript

1,873

A Reactive Programming library for JavaScript

Quick Overview

Most.js is a powerful and efficient reactive programming library for JavaScript. It provides a set of tools for working with event streams and functional programming concepts, allowing developers to build complex asynchronous applications with ease.

Pros

  • High performance and efficiency, optimized for handling large amounts of data
  • Extensive API with a wide range of operators for stream manipulation
  • Excellent TypeScript support with comprehensive type definitions
  • Lightweight and modular design, allowing for tree-shaking in modern build systems

Cons

  • Steeper learning curve compared to some other reactive libraries
  • Less community support and resources compared to more popular alternatives like RxJS
  • Documentation can be sparse or unclear in some areas
  • Not actively maintained (last commit was in 2019)

Code Examples

Creating a simple stream:

import { from } from '@most/core';
import { newDefaultScheduler } from '@most/scheduler';

const scheduler = newDefaultScheduler();
const stream = from([1, 2, 3, 4, 5]);

stream.run({
  event: x => console.log(x),
  error: e => console.error(e),
  end: () => console.log('Done')
}, scheduler);

Mapping and filtering a stream:

import { from, map, filter } from '@most/core';
import { newDefaultScheduler } from '@most/scheduler';

const scheduler = newDefaultScheduler();
const stream = from([1, 2, 3, 4, 5]);

const doubledEvenNumbers = stream.pipe(
  filter(x => x % 2 === 0),
  map(x => x * 2)
);

doubledEvenNumbers.run({
  event: x => console.log(x),
  error: e => console.error(e),
  end: () => console.log('Done')
}, scheduler);

Combining multiple streams:

import { from, merge } from '@most/core';
import { newDefaultScheduler } from '@most/scheduler';

const scheduler = newDefaultScheduler();
const stream1 = from([1, 2, 3]);
const stream2 = from([4, 5, 6]);

const combinedStream = merge(stream1, stream2);

combinedStream.run({
  event: x => console.log(x),
  error: e => console.error(e),
  end: () => console.log('Done')
}, scheduler);

Getting Started

To get started with Most.js, first install it using npm:

npm install @most/core @most/scheduler

Then, import the necessary functions and create a scheduler:

import { from } from '@most/core';
import { newDefaultScheduler } from '@most/scheduler';

const scheduler = newDefaultScheduler();

// Create and use streams here
const stream = from([1, 2, 3]);

stream.run({
  event: x => console.log(x),
  error: e => console.error(e),
  end: () => console.log('Done')
}, scheduler);

This basic setup allows you to start working with Most.js streams in your project.

Competitor Comparisons

30,605

A reactive programming library for JavaScript

Pros of RxJS

  • Larger community and ecosystem, with more resources and third-party libraries
  • Extensive operator set, providing a wide range of built-in functionality
  • Better TypeScript support and integration

Cons of RxJS

  • Larger bundle size, which can impact performance in some applications
  • Steeper learning curve due to its extensive API and concepts
  • Higher memory usage in certain scenarios

Code Comparison

most:

import { from } from 'most';

from([1, 2, 3, 4])
  .map(x => x * 2)
  .filter(x => x > 5)
  .reduce((acc, x) => acc + x, 0)
  .then(result => console.log(result));

RxJS:

import { from } from 'rxjs';
import { map, filter, reduce } from 'rxjs/operators';

from([1, 2, 3, 4]).pipe(
  map(x => x * 2),
  filter(x => x > 5),
  reduce((acc, x) => acc + x, 0)
).subscribe(result => console.log(result));

Both libraries provide similar functionality for creating and manipulating streams of data. most focuses on performance and a smaller API surface, while RxJS offers a more comprehensive set of features and better ecosystem support. The choice between them depends on specific project requirements, performance needs, and developer familiarity with reactive programming concepts.

Observables for ECMAScript

Pros of proposal-observable

  • Standardized approach for observables in JavaScript
  • Potential for native browser support in the future
  • Broader ecosystem compatibility due to standardization

Cons of proposal-observable

  • Still in proposal stage, not yet finalized
  • Limited functionality compared to more mature libraries
  • Slower adoption and implementation process

Code Comparison

proposal-observable:

const observable = new Observable(observer => {
  observer.next(1);
  observer.next(2);
  observer.complete();
});

most:

import {from} from 'most';

const stream = from([1, 2]);

Key Differences

  • most is a fully-featured reactive programming library, while proposal-observable is a standardization effort
  • most offers more advanced operators and utilities for stream manipulation
  • proposal-observable aims to provide a common foundation for observable implementations across libraries

Use Cases

  • proposal-observable: Ideal for projects requiring a standardized, future-proof observable implementation
  • most: Better suited for complex reactive programming scenarios with advanced stream operations
2,375

An extremely intuitive, small, and fast functional reactive stream library for JavaScript

Pros of xstream

  • Smaller bundle size and simpler API, making it more lightweight
  • Designed specifically for Cycle.js, offering seamless integration
  • Provides a "hot" by default approach, which can be more intuitive for some use cases

Cons of xstream

  • Less comprehensive operator set compared to most
  • Lower performance in some scenarios, especially with large data streams
  • Limited community and ecosystem compared to more established libraries like most

Code Comparison

xstream:

import xs from 'xstream';

const stream = xs.periodic(1000).map(i => i * 2);
stream.addListener({
  next: i => console.log(i),
  error: err => console.error(err),
  complete: () => console.log('completed')
});

most:

import { periodic } from '@most/core';
import { map, runEffects } from '@most/core';
import { newDefaultScheduler } from '@most/scheduler';

const stream = map(x => x * 2, periodic(1000));
runEffects(tap(console.log, stream), newDefaultScheduler());

Both examples create a stream that emits doubled values every second. xstream uses a more object-oriented approach with listeners, while most employs a more functional style with composable operators.

1,559

👜 A standard for JS callbacks that enables lightweight observables and iterables

Pros of Callbag

  • Lightweight and minimalistic approach
  • Flexible and protocol-based, allowing for easy creation of custom operators
  • Language-agnostic, can be implemented in various programming languages

Cons of Callbag

  • Less mature ecosystem compared to Most
  • Steeper learning curve due to its low-level nature
  • Fewer built-in operators and utilities out of the box

Code Comparison

Most:

import { from, map, filter } from 'most'

from([1, 2, 3, 4])
  .map(x => x * 2)
  .filter(x => x > 5)
  .observe(x => console.log(x))

Callbag:

import { fromIter, map, filter, forEach } from 'callbag-basics'

pipe(
  fromIter([1, 2, 3, 4]),
  map(x => x * 2),
  filter(x => x > 5),
  forEach(x => console.log(x))
)

Both Most and Callbag provide reactive programming capabilities, but they differ in their approach and implementation. Most offers a more traditional streaming library with a rich set of operators and optimizations for performance. Callbag, on the other hand, provides a minimal core protocol that can be extended with custom operators, making it more flexible but potentially requiring more setup work.

Functional reactive programming library for TypeScript and JavaScript

Pros of Bacon.js

  • More mature and established project with a larger community
  • Comprehensive documentation and extensive examples
  • Supports both Node.js and browser environments out of the box

Cons of Bacon.js

  • Larger bundle size, which may impact performance in browser applications
  • Less focus on high-performance streaming compared to Most.js
  • Not as actively maintained in recent years

Code Comparison

Bacon.js:

Bacon.fromEvent(document, 'click')
  .map(e => e.clientX)
  .filter(x => x > 100)
  .onValue(x => console.log(x));

Most.js:

most.fromEvent('click', document)
  .map(e => e.clientX)
  .filter(x => x > 100)
  .observe(x => console.log(x));

Both libraries provide similar functionality for creating and manipulating event streams. The syntax is slightly different, with Bacon.js using method chaining and Most.js using a more functional approach. Most.js is designed to be more performant, especially for high-throughput applications, while Bacon.js offers a more familiar API for developers coming from other reactive programming libraries.

1,873

A Reactive Programming library for JavaScript

Pros of Kefir

  • More intuitive API, easier for beginners to grasp
  • Better performance for synchronous operations
  • Smaller bundle size, beneficial for browser-based applications

Cons of Kefir

  • Less comprehensive documentation compared to Most
  • Fewer advanced features and operators
  • Smaller community and ecosystem

Code Comparison

Kefir:

Kefir.sequentially(1000, [1, 2, 3])
  .map(x => x * 2)
  .filter(x => x > 2)
  .onValue(x => console.log(x))

Most:

most.from([1, 2, 3])
  .periodic(1000)
  .map(x => x * 2)
  .filter(x => x > 2)
  .observe(x => console.log(x))

Both libraries provide similar functionality for creating and manipulating streams of data. Kefir's API is often considered more straightforward, while Most offers more advanced features and better performance for asynchronous operations. The choice between the two depends on specific project requirements, performance needs, and developer preferences.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

________________________________
___   |/  /_  __ \_  ___/__  __/
__  /|_/ /_  / / /____ \__  /   
_  /  / / / /_/ /____/ /_  /    
/_/  /_/  \____/______/ /_/

Monadic streams for reactive programming

Greenkeeper badge

Build Status Join the chat at https://gitter.im/cujojs/most

Starting a new project?

Strongly consider starting with @most/core. It is the foundation of the upcoming most 2.0, has improved documentation, new features, better tree-shaking build characteristics, and simpler APIs. Updating from @most/core to most 2.0 will be non-breaking and straightforward.

Using most 1.x already on an existing project?

You can keep using most 1.x, and update to either @most/core or most 2.0 when you're ready. See the upgrade guide for more information.

What is it?

Most.js is a toolkit for reactive programming. It helps you compose asynchronous operations on streams of values and events, e.g. WebSocket messages, DOM events, etc, and on time-varying values, e.g. the "current value" of an <input>, without many of the hazards of side effects and mutable shared state.

It features an ultra-high performance, low overhead architecture, APIs for easily creating event streams from existing sources, like DOM events, and a small but powerful set of operations for merging, filtering, transforming, and reducing event streams and time-varying values.

Learn more

Simple example

Here's a simple program that displays the result of adding two inputs. The result is reactive and updates whenever either input changes.

First, the HTML fragment for the inputs and a place to display the live result:

<form>
	<input class="x"> + <input class="y"> = <span class="result"></span>
</form>

Using most.js to make it reactive:

import { fromEvent, combine } from 'most'

const xInput = document.querySelector('input.x')
const yInput = document.querySelector('input.y')
const resultNode = document.querySelector('.result')

const add = (x, y) => x + y

const toNumber = e => Number(e.target.value)

const renderResult = result => {
	resultNode.textContent = result
}

export const main = () => {
	// x represents the current value of xInput
	const x = fromEvent('input', xInput).map(toNumber)

	// y represents the current value of yInput
	const y = fromEvent('input', yInput).map(toNumber)

	// result is the live current value of adding x and y
	const result = combine(add, x, y)

	// Observe the result value by rendering it to the resultNode
	result.observe(renderResult)
}

More examples

You can find the example above and others in the Examples repo.

Get it

Requirements

Most requires ES6 Promise. You can use your favorite polyfill, such as creed, when, bluebird, es6-promise, etc. Using a polyfill can be especially beneficial on platforms that don't yet have good unhandled rejection reporting capabilities.

Install

As a module:

npm install --save most
// ES6
import { /* functions */ } from 'most'
// or
import * as most from 'most'
// ES5
var most = require('most')

As window.most:

bower install --save most
<script src="most/dist/most.js"></script>

As a library via cdn :

<!-- unminified -->
<script src="https://unpkg.com/most/dist/most.js"></script>
<!-- minified -->
<script src="https://unpkg.com/most/dist/most.min.js"></script>

Typescript support

Most.js works with typescript out of the box as it provides local typings that will be read when you import Most.js in your code. You do not need to manually link an external d.ts file in your tsconfig.

Most.js has a dependency on native Promises so a type definition for Promise must be available in your setup:

  • If your tsconfig is targeting ES6, you do not need to do anything as typescript will include a definition for Promise by default.
  • If your tsconfig is targeting ES5, you need to provide your own Promise definition. For instance es6-shim.d.ts

Interoperability

Promises/A+ Fantasy Land

Most.js streams are compatible with Promises/A+ and ES6 Promises. They also implement Fantasy Land and Static Land Semigroup, Monoid, Functor, Apply, Applicative, Chain and Monad.

Reactive Programming

Reactive programming is an important concept that provides a lot of advantages: it naturally handles asynchrony and provides a model for dealing with complex data and time flow while also lessening the need to resort to shared mutable state. It has many applications: interactive UIs and animation, client-server communication, robotics, IoT, sensor networks, etc.

Why most.js for Reactive Programming?

High performance

A primary focus of most.js is performance. The perf test results indicate that it is achieving its goals in this area. Our hope is that by publishing those numbers, and showing what is possible, other libs will improve as well.

Modular architecture

Most.js is highly modularized. It's internal Stream/Source/Sink architecture and APIs are simple, concise, and well defined. Combinators are implemented entirely in terms of that API, and don't need to use any private details. This makes it easy to implement new combinators externally (ie in contrib repos, for example) while also guaranteeing they can still be high performance.

Simplicity

Aside from making combinators less "obviously correct", complexity can also lead to performace and maintainability issues. We felt a simple implementation would lead to a more stable and performant lib overall.

Integration

Most.js integrates with language features, such as promises, iterators, generators, and asynchronous generators.

Promises

Promises are a natural compliment to asynchronous reactive streams. The relationship between synchronous "sequence" and "value" is clear, and the asynchronous analogue needs to be clear, too. By taking the notion of a sequence and a value and lifting them into the asynchronous world, it seems clear that reducing an asynchronous sequence should produce a promise. Hence, most.js uses promises when a single value is the natural synchronous analogue.

Most.js interoperates seamlessly with ES6 and Promises/A+ promises. For example, reducing a stream returns a promise for the final result:

import { from } from 'most'
// After 1 second, logs 10
from([1, 2, 3, 4])
	.delay(1000)
	.reduce((result, y) => result + y, 0)
	.then(result => console.log(result))

You can also create a stream from a promise:

import { fromPromise } from 'most'
// Logs "hello"
fromPromise(Promise.resolve('hello'))
	.observe(message => console.log(message))

Generators

Conceptually, generators allow you to write a function that acts like an iterable sequence. Generators support the standard ES6 Iterator interface, so they can be iterated over using ES6 standard for of or the iterator's next() API.

Most.js interoperates with ES6 generators and iterators. For example, you can create an event stream from any ES6 iterable:

import { from } from 'most'

function* allTheIntegers() {
	let i=0
	while(true) {
		yield i++
	}
}

// Log the first 100 integers
from(allTheIntegers())
	.take(100)
	.observe(x => console.log(x))

Asynchronous Generators

You can also create an event stream from an asynchronous generator, a generator that yields promises:

import { generate } from 'most'

function* allTheIntegers(interval) {
	let i=0
	while(true) {
		yield delayPromise(interval, i++)
	}
}

const delayPromise = (ms, value) =>
	new Promise(resolve => setTimeout(() => resolve(value), ms))

// Log the first 100 integers, at 1 second intervals
generate(allTheIntegers, 1000)
	.take(100)
	.observe(x => console.log(x))

NPM DownloadsLast 30 Days