• Stars
    star
    161
  • Rank 233,470 (Top 5 %)
  • Language
    HTML
  • Created about 11 years ago
  • Updated over 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Clojurescript library for interacting with web workers sanely

Servant

A Clojurescript library for interacting with webworkers sanely

Installation

add Clojars Project to your dependencies

Usage

Web workers are a pain to use, manage, and create, but they offer the ability of spawning real threads. This library seeks to give you the good parts, without any of the bad parts.

Through the magic of core.async's channels, we can abstract out a lot of the implementation details in webworkers. And with some careful execution, we can run the web workers in a similar context.

Spawning Servants

We create all our web workers at once and keep them on hand in a pool of available workers.
Any worker can run any function, so servants do not store any state.

(def worker-count 2) ;; how many servants we want in our servant-pool
(def worker-script "/main.js") ;; This is whatever the name of the compiled javascript will be

;; We need to make sure that only the main script will spawn the servants.
(when-not (servant/webworker?)
  ;; We keep all the servants in a buffered channel.
  (def servant-channel (servant/spawn-servants worker-count worker-script)))

Defining Functions

We define functions that servants should be able to execute with defservantfn. It is crucial that these functions be pure.

Under the hood, defservantfn creates a normal function, but it also tells the webworker to remember this function.

  (defservantfn some-random-fn [a b]
    (+ a b))
  ;; This can also call other functions within the scope!

  (defn make-it-funny [not-funny]
    (str "Hahahah:" not-funny))

  (defservantfn servant-with-humor [your-joke]
    (make-it-funny your-joke))

Using a servant

To make a call you need to wire up your servant by providing the servant-channel, a message sending fn, and your defined servant fn.

  • Servant-channel: Allows the function to figure out to whom it should dispatch the work.
  • message-fn: Determines how the lowlevel worker.postMessage is called. The simplest is defined in servant/standard-message.
  • servant-fn: This is the defservantfn we created earlier
  • & args
  (def result-channel (servant/servant-thread servant-channel servant/standard-message servant-fn 5 6))

This will call the servant-fn using a servant from the pool with the args 5 6.
This will return a channel that will contain the result. Similar to how core.async's thread works.

Caveats

Web workers have a completely separate context from the main running script, so to be able to call functions freely, we use the same file for the main browser thread, and web workers. But doing that comes at a cost, you have to prevent the webworker from running code meant for the browser.

Our current solution is:

(defn window-load []
  ;; your browser specific code here
  )

(if (servant/webworker?)
  (worker/bootstrap) ;; Run the setup code for the web worker
  (set! (.-onload js/window) window-load)  ;; run the browser specific code
  )

Separate Worker file

Sometimes you want to have a separate cljs file for workers, and that's fine!
Nothing in this library prevents you from that.

Do the same thing you did before, but now this will run in a separate (possibly smaller) js file.
You simply need to figure out what's the best way to pass data around the main browser context, which is significantly easier because they share the context!

Examples

Simple example project
Encrypt/Decrypt Project using webworkers

Testing

I can't seem to figure out a good way to test web workers :(, I'd love to hear some ideas!

TODO

Write tests.

License

Copyright © 2013 Marco Munizaga

Distributed under the Eclipse Public License, the same as Clojure.

More Repositories

1

lt-markdown

Light table plugin for live editing markdown.
JavaScript
42
star
2

zig-libp2p

Zig
34
star
3

Mac-n-Cheese

Bypass the need for authentication/payment on wifi hotspots
Python
19
star
4

atom-paredit

Paredit implementation for Atom using Clojurescript
JavaScript
17
star
5

y-libp2p

Yjs provider using libp2p
JavaScript
15
star
6

simple-vms

Simple VMs in NixOS
Nix
9
star
7

om-server-render

A minimal example project of server side rendering with om
Clojure
9
star
8

lt-chrome-extension

A chrome extension to facilitate connecting to chrome.
JavaScript
8
star
9

gossip-pad

Collaborative markdown editor build with Yjs, libp2p, and Slatejs
TypeScript
8
star
10

firecracker-containerd-nix

Nix
7
star
11

servant-crypt-demo

Demo of the servant library using cryptography!
Clojure
7
star
12

zig-msquic

A small Zig library that wraps MsQuic
Zig
6
star
13

servant-demo

A Simple demo of the servant library.
Clojure
5
star
14

keybase-bot-api

A Keybase bot API for Rust
Rust
5
star
15

iso-country-codes

Clojure library for translating iso country codes
Clojure
5
star
16

design-patterns

Notes on Design Patterns Class with Dave
Java
4
star
17

Conway-game-of-life-JS-html5

Game of life written in JS + html5
JavaScript
4
star
18

android-wired

Wired, a Rust based zero cost UI Framework for Android *WIP* pre pre-alpha
Rust
4
star
19

btc-e-client

Clojure Client for BTC-e.com
Clojure
4
star
20

crypticcandy

Secure upload/download of large files
JavaScript
3
star
21

lt-tmux

Light Table plugin for sending text to a tmux session
JavaScript
3
star
22

MariumAquarium

A virtual, interactive aquarium with Mario characters.
Java
3
star
23

terrafirma-scraper

A scraper endpoint in wasm on Terrafirma
Rust
3
star
24

lt-pgp

Edit encrypted files inside Light Table
JavaScript
3
star
25

gsplayerApi

Node server working as an api for the grooveshark player
JavaScript
3
star
26

tubeShark

Chrome extension that automagically controls grooveshark when you watch a youtube video
JavaScript
3
star
27

pythonProjects

Random Projects written in Python
Python
2
star
28

datastructures

COP3530
C++
2
star
29

lightbase-backend

A glorified pub/sub server.
Clojure
2
star
30

words-with-friends-query

Words with friends? Are you talking to a stranger or your friend?? You tell me!
Rust
2
star
31

rssPlugin

allows Grooveshark to use RSS feeds
JavaScript
2
star
32

husky-blocker-2000

Nix
2
star
33

marcopolo.github.io

Partially Functional
HTML
2
star
34

jdowd7

2
star
35

Marco-website

simple homepage website
JavaScript
2
star
36

stress.js

stress test ajax stuff using node
JavaScript
2
star
37

transcience

game that questions the very essence of life itself
JavaScript
2
star
38

linkit

lol links
JavaScript
2
star
39

slack-keybase-bridge

A Bridge between Slack <-> Keybase messages
Rust
2
star
40

dotfiles

My configs
Nix
2
star
41

js-libp2p-fetch

Fetch API on js-libp2p streams
JavaScript
2
star
42

piet-android-demo

Android App Demo for piet-android
Rust
2
star
43

sudoku-JS-solver

solves sudoku puzzles using js
JavaScript
2
star
44

Helpy-Bot

It's a helpful bot. Made for Innovation Hub hackathon with @Marcopolo and @L1fescape.
1
star
45

go-libp2p-extras

Extra tidbits for go-libp2p
Go
1
star
46

MaraudersMap

This is a map that displays a person's location within a building using laser sensors with an arduino. Google Science Fair Project.
Java
1
star
47

collection-backend

Backend for Collection project which is for the launch hackathon
Clojure
1
star
48

syndicate-rss

Copies posts from an RSS feed to a markdown file suitable for Zola. Used to syndicate content.
TypeScript
1
star
49

flowToTs

Flow to Typescript codemod
TypeScript
1
star
50

GrooviTunes

Java application that imports an xml library and creates a grooveshark playlist
Java
1
star
51

rust-android-boilerplate

An Example of a hello world Rust library wrapped in an Android App
Rust
1
star
52

core.emoji

Clojure, simple made emoji
Clojure
1
star
53

SharkByte

Python
1
star
54

home

Nix
1
star
55

wootLights

Way to get woot lights to work with git commits
Shell
1
star
56

btc-ticker-cli

Silly little console ticker
Shell
1
star
57

clojuretip

Clojure tip of the day
Clojure
1
star
58

go-wasm-terrafirma

A subset of the terrarium WASM interface in Go. For use with kbwasm.
Go
1
star
59

pageNotifier

Python script that listens for web site changes and texts you when it finds a change!
Python
1
star
60

Random-Project-ideas

Project ideas that are half built and aren't really reliable.
1
star
61

Desktopography-Downloader

Downloads wallpapers from Desktopography.net
Python
1
star
62

nsa-slackbot

Bot that records conversations; nothing to see here.
Rust
1
star
63

storm-playground

random storm stuff
Clojure
1
star
64

sig-verifier-chrome

Plugin for chrome that will verify the files loaded on a page
JavaScript
1
star
65

linkMyDots

Small shell script populates a dotfile folder
Shell
1
star
66

kb-log-viewer

Pretty Print Keybase Logs
JavaScript
1
star
67

gltut-rs

Working through https://paroj.github.io/gltut/ in Rust
Rust
1
star