Fiber
The Fiber API provides low level concurrency handles, that helps in writing asynchronous programs which can be paused or aborted.
Fiber is represented with two type params viz.
AThe type of the success value that will be emitted once the Fiber is completely evaluated.EThe error type that can be emitted in case of failure.
interface Fiber<A, E> {
join: QIO<A, E>
abort: QIO<void>
}
Use case
Consider running the following program:
import {QIO} from '@qio/core'
const putStrLn = QIO.encase(console.log)
const A = putStrLn('A').delay(1000) // QIO<string>
const B = putStrLn('B') // QIO<string>
const program = A.and(B)
Output
A
B
A is printed first and then B is printed. This guarantee is provided by the and operator.
To make sure that the computation continues with B and doesn't wait for A to complete we can use the fork() operator on A.
import {QIO} from '@qio/core'
const putStrLn = QIO.encase(console.log)
- const A = putStrLn('A').delay(1000) // QIO<string>
+ const A = putStrLn('A').delay(1000).fork() // QIO<Fiber<string>>
const B = putStrLn('B') // QIO<string>
const program = A.and(B)
Output
B
A
Calling fork() makes sure that A runs in its own Fiber, asynchronously and moves on to computing B as soon as possible. That way B is printed first and then after 1000ms, A is printed.
F.abort
import {QIO} from '@qio/core'
const putStrLn = QIO.encase(console.log)
- const A = putStrLn('A').delay(1000).fork()
+ const A = putStrLn('A').delay(1000).fork().chain(F => F.abort.delay(100))
const B = putStrLn('B')
const program = A.and(B)
Output:
B
F represents a Fiber and using abort.delay(100) we are aborting the computation after 100ms that way A is never computed and thus only B is printed on the screen.
F.join
import {QIO} from '@qio/core'
const putStrLn = QIO.encase(console.log)
- const A = putStrLn('A').delay(1000).fork().chain(F => F.abort.delay(100))
+ const A = putStrLn('A').delay(1000).fork().chain(F => F.join)
const B = putStrLn('B')
const program = A.and(B)
Output:
A
B
F.join waits for the fiber to compute its value and move on to the next. In the above case A is printed after 1000ms and then immediately B is printed.
Once the fiber is computed internally, using join multiple times will resolve with the same cached, value every time.