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)->Belt.Option.getExn;
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```