Mirror: 馃帺 A tiny but capable push & pull stream library for TypeScript and Flow
1--- 2title: Sources 3order: 0 4--- 5 6A "source" in Wonka is a provider of data. It provides data to a "sink" when the "sink" requests it. This is called a pull signal and for synchronous sources no time will pass between the sink pulling a new value and a source sending it. For asynchronous sources, the source may either ignore pull signals and just push values or send one some time after the pull signal. 7 8## fromArray 9 10`fromArray` transforms an array into a source, emitting each item synchronously. 11 12```reason 13Wonka.fromArray([|1, 2, 3|]); 14``` 15 16```typescript 17import { fromArray } from 'wonka'; 18fromArray([1, 2, 3]); 19``` 20 21## fromList 22 23`fromList` transforms a list into a source, emitting each item synchronously. 24 25> _Note:_ This operator is only useful in Reason / OCaml where lists are a builtin 26> data structure. 27 28This is otherwise functionally the same as `fromArray`. 29 30```reason 31Wonka.fromList([1, 2, 3]); 32``` 33 34## fromValue 35 36`fromValue` takes a single value and creates a source that emits the value and 37completes immediately afterwards. 38 39```reason 40Wonka.fromValue("a value"); 41``` 42 43## make 44 45`make` can be used to create an arbitrary source. It allows you to make a source 46from any other data. 47It accepts a function that receives an "observer" and should return a teardown 48function. It's very similar to creating an [Observable in `zen-observable`](https://github.com/zenparsing/zen-observable#new-observablesubscribe). 49 50The function you pass to `make` is called lazily when a sink subscribes to the 51source you're creating. The first argument `observer` is a tuple with two methods: 52 53- `next(value)` emits a value on the sink 54- `complete()` ends the source and completes the sink 55 56The subscriber function also needs ot return a `teardown` function. This function 57is called when either `complete()` is called and the source ends, or if the source 58is being cancelled, since the sink unsubscribed. 59 60In this example we create a source that waits for a promise to resolve and emits 61values from the array of that promise. 62 63```reason 64let waitForArray = () => Js.Promise.resolve([|1, 2, 3|]); 65 66let source = Wonka.make((. observer) => { 67 let (next, complete) = observer; 68 let cancelled = ref(false); 69 let promise = waitForArray(); 70 71 Js.Promise.then_(arr => { 72 if (!cancelled^) { 73 Array.iter(next, arr); 74 complete(); 75 } 76 }, promise); 77 78 () => cancelled := true; 79}); 80``` 81 82```typescript 83import { make } from 'wonka'; 84 85const waitForArray = () => Promise.resolve([1, 2, 3]); 86 87const source = make(observer => { 88 const [next, complete] = observer; 89 let cancelled = false; 90 91 waitForArray().then(arr => { 92 if (!cancelled) { 93 arr.forEach(next); 94 complete(); 95 } 96 }); 97 98 return () => { 99 cancelled = true; 100 }; 101}); 102``` 103 104## makeSubject 105 106`makeSubject` can be used to create a subject. This is similar to [`make`](#make) without 107having to define a source function. Instead a subject is a tuple of a source and 108the observer's `next` and `complete` functions combined. 109 110A subject can be very useful as a full event emitter. It allows you to pass a source 111around but also have access to the observer functions to emit events away from 112the source itself. 113 114```reason 115let subject = Wonka.makeSubject(); 116let { source, next, complete } = subject; 117 118/* This will push the values synchronously to any subscribers of source */ 119next(1); 120next(2); 121next(complete); 122``` 123 124```typescript 125import { makeSubject } from 'wonka' 126const subject = Wonka.makeSubject(); 127const [source, next, complete] = subject; 128 129/* This will push the values synchronously to any subscribers of source */ 130next(1); 131next(2); 132next(complete); 133``` 134 135## fromDomEvent 136 137`fromDomEvent` will turn a DOM event into a Wonka source, emitting the DOM events 138on the source whenever the DOM emits them on the passed element. 139 140> _Note:_ This source is only available in JavaScript environments, and will be excluded 141> when compiling natively. 142 143```reason 144open WebApi.Dom; 145open Document; 146 147let element = getElementById("root", document); 148 149Wonka.fromDomEvent(element, "click") 150 |> Wonka.subscribe((. click) => Js.log(click)); 151``` 152 153```typescript 154import { pipe, fromDomEvent, subscribe } from 'wonka'; 155 156const element = document.getElementById('root'); 157 158pipe( 159 fromDomEvent(element, 'click'), 160 subscribe(e => console.log(e)) 161); 162``` 163 164## fromPromise 165 166`fromPromise` transforms a promise into a source, emitting the promisified value on 167the source once it resolves. 168 169> _Note:_ This source is only available in JavaScript environments, and will be excluded 170> when compiling natively. 171 172```reason 173let promise = Js.Promise.make(1); /* Just an example promise */ 174 175Wonka.fromPromise(promise) 176 |> Wonka.subscribe((. x) => Js.log(x)); 177/* Prints 1 to the console. */ 178``` 179 180```typescript 181import { pipe, fromPromise, subscribe } from 'wonka'; 182 183const promise = Promise.resolve(1); // Just an example promise 184 185pipe( 186 fromPromise(promise), 187 subscribe(e => console.log(e)) 188); // Prints 1 to the console. 189``` 190 191## fromObservable 192 193`fromObservable` transforms a [spec-compliant JS Observable](https://github.com/tc39/proposal-observable) into a source. 194The resulting source will behave exactly the same as the Observable that it was 195passed, so it will start, end, and push values identically. 196 197> _Note:_ This source is only available in JavaScript environments, and will be excluded 198> when compiling natively. 199 200```typescript 201import { pipe, fromObservable, subscribe } from 'wonka'; 202 203// This example uses zen-observable for illustrative purposes 204import Observable from 'zen-observable'; 205 206const observable = Observable.from([1, 2, 3]); 207 208pipe( 209 fromObservable(observable), 210 subscribe(e => console.log(e)) 211); // Prints 1 2 3 to the console 212``` 213 214If you're using Reason in a JavaScript environment and you're interested in this 215operator, you may be using a library to create or get Observables. 216 217Some libraries don't expose Observables with the same BuckleScript type signature 218that Wonka uses to type them. So while Wonka's `observableT` type is fairly 219lenient it may not work for you. 220 221```reason 222type observableT('a) = {. 223 [@bs.meth] "subscribe": observerT('a) => subscriptionT 224}; 225``` 226 227To work around this you can create a function that casts your observable type 228to Wonka's `observableT`. 229 230```reason 231type yourObservableType('a); 232external asObservable: yourObservableType('a) => Wonka.observableT('a) = "%identity"; 233``` 234 235This snippet would create an `asObservable` function, which can type-cast your 236Observable type to `Wonka.observableT` and compiles away completely. 237 238## fromCallbag 239 240`fromCallbag` transforms a [spec-compliant JS Callbag](https://github.com/callbag/callbag) into a source. 241 242Since Wonka's sources are very similar to callbags and only diverge from the specification 243minimally, Callbags map to Wonka's sources very closely and the `fromCallbag` wrapper 244is very thin and mostly concerned with converting between the type signatures. 245 246> _Note:_ This source is only available in JavaScript environments, and will be excluded 247> when compiling natively. 248 249```reason 250/* This example uses the callbag-from-iter package for illustrative purposes */ 251[@bs.module] external callbagFromArray: 252 array('a) => Wonka.callbagT('a) = "callbag-from-iter"; 253 254let callbag = callbagFromArray([|1, 2, 3|]); 255 256Wonka.fromCallbag(callbag) 257 |> Wonka.subscribe((. x) => Js.log(x)); 258/* Prints 1 2 3 to the console. */ 259``` 260 261```typescript 262import { pipe, fromCallbag, subscribe } from 'wonka'; 263 264// This example uses the callbag-from-iter package for illustrative purposes 265import callbagFromArray from 'callbag-from-iter'; 266 267const callbag = callbagFromArray([1, 2, 3]); 268 269pipe( 270 fromCallbag(callbag), 271 subscribe(e => console.log(e)) 272); // Prints 1 2 3 to the console. 273``` 274 275## interval 276 277`interval` creates a source that emits values after the given amount of milliseconds. 278Internally it uses `setInterval` to accomplish this. 279 280> _Note:_ This source is only available in JavaScript environments, and will be excluded 281> when compiling natively. 282 283```reason 284Wonka.interval(50) 285 |> Wonka.subscribe((. x) => Js.log(x)); 286/* Prints 0 1 2... to the console. */ 287/* The incrementing number is logged every 50ms */ 288``` 289 290```typescript 291import { pipe, interval, subscribe } from 'wonka'; 292 293pipe( 294 interval(50), 295 subscribe(e => console.log(e)) 296); // Prints 0 1 2... to the console. 297// The incrementing number is logged every 50ms 298``` 299 300## empty 301 302This is a source that doesn't emit any values when subscribed to and 303immediately completes. 304 305```reason 306Wonka.empty 307 |> Wonka.forEach((. value) => { 308 /* This will never be called */ 309 () 310 }); 311``` 312 313```typescript 314import { pipe, empty, forEach } from 'wonka'; 315 316pipe( 317 empty, 318 forEach(value => { 319 /* This will never be called */ 320 }) 321); 322``` 323 324## never 325 326This is source is similar to [`empty`](#empty). 327It doesn't emit any values but also never completes. 328 329```reason 330Wonka.never 331 |> Wonka.forEach((. value) => { 332 /* This will never be called */ 333 () 334 }); 335``` 336 337```typescript 338import { pipe, never, forEach } from 'wonka'; 339 340pipe( 341 never, 342 forEach(value => { 343 /* This will never be called */ 344 }) 345); 346```