
Não, não estou doente. Pelo menos é o que diz a voz na minha cabeça. Eu sou um viciado Estou na agulha há mais de 15 anos. Uso muito, forte, até desmaiar. Cheguei ao ponto de que ultimamente não tenho vergonha de meus amigos, minha esposa ou meus filhos ... Dois filhos! Não gosto de badazhenny, gosto de limpar, sem impurezas. Tentei muito ao longo dos anos, mas recentemente parei de procurar. É engraçado perceber que você obtém dor e alegria da mesma coisa. Eu gostaria de ir fazer tratamento, até quero, até sei qual. Você conhece aqueles em que continua usando, mas sob supervisão?
typescript. — . , , . , , , , . -, , , , - . , , - , , ...
, es- — . ruby javascript, , - — yield? ! , — : ? ? /? Oh My God!
. , , - , , , . , , , , yield yield , , - . , . - , , ...
-. — react + mobx. , / , , , , , , , , … , , — , , , .
- . MV* , — . — * ! ? — , M , V , , , !
, typescript. , , Maximum call stack size exceeded — ? , , , , .
. . , , . Html- — , ? ? ? , , — , — — , ...
- " " — , , , . : " , — " — — "! !". ! ?)
- . . , , , , , . ? , — , , , , ? — 19 , , 1844 , 1862 , , . . , , . , - ? ? , , , , … … ? ? ?
! ! , , - . , . , . — , .
, , 3 , ~800 git- . yield*. -, . return ? , , , .
async function* SiriusA() {
return '*A' //
}
async function* SiriusB() {
return '*B' //
}
async function* Sirius() {
// ['*A', '*B']
return [yield* SiriusA(), yield* SiriusB()]
}
async function* CanisMajor() {
const sirius = yield* Sirius() // ['*A', '*B']
// -
}
-. : " ? " — , . yield*. , return- " " yield-, — , , , . — , : " ", ~300 . , , - - , , . .
, . , , — . , , — .
, , , .., - , . — , .

@fract/core — — , : fractal fraction. , . , , npm yield*.
Hello world , ,
import { fractal, fraction } from '@fract/core'
const Title = fraction('Hello world')
const HelloWorld = fractal(async function* () {
while (true) yield `App: ${yield* Title}`
})
, — , . — , , .use(data).
yield , yield* , — , yield* — , yield . pull & push.

, :
-
yieldreturn— ,yield*; , , - , ,
yield, ;return
return , yield — , "" .
, . , .
interface Frame<T> {
data: T;
}
, . , - , .
interface LiveFrame<T> extends Frame<T> {
next: Promise<LiveFrame<T>>;
}
— , : .
exec live. ( ) , .
import { exec, live } from '@fract/core'
exec<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<Frame<T>>
, .
const frame = await exec(HelloWorld)
frame.data // 'App: Hello world'
live<T>(target: Fractal<T> | AsyncGenerator<T>): Promise<LiveFrame<T>>
, .
const frame = await live(HelloWorld)
frame.data // 'App: Hello world'
Title.use('Fractal Demo')
const nextFrame = await frame.next
nextFrame.data // 'App: Fractal Demo'
, ,
const Name = fraction('John')
const Age = fraction(33)
const Balance = fraction(100)
const Card = fractal(async function* () {
while (true) {
yield {
balance: yield* Balance,
}
}
})
const User = fractal(async function* () {
while (true) {
yield {
name: yield* Name,
age: yield* Age,
card: yield* Card,
}
}
})
const frame = await exec(Balance)
frame.data //> 100
const frame = await exec(Card)
frame.data //> {balance: 100}
const frame = await exec(User)
frame.data
/*
> {
name: 'John',
age: 33,
wallet: {
balance: 100
}
}
*/
exec , live —
const frame = await live(User)
console.log(frame.data)
/*
> {
name: 'John',
age: 33,
card: {
balance: 100
}
}
*/
Name.use('Barry')
Balance.use(200)
const nextFrame = await frame.next
console.log(nextFrame.data)
/*
> {
name: 'Barry',
age: 33,
card: {
balance: 200
}
}
*/
, , User ( ), undefined ( )
const App = fractal(async function* () {
while (true) {
console.log(yield* User)
yield
}
})
live(App) //

, — .
, , — . , , — Promise<LiveFrame<T>>[], racers, , Promise.race(racers) — — racer , racers — .

Promise.race([
// level 1
Promise.race([/* ... */]),
Promise.race([/* ... */]),
Promise.race([
// level 2
Promise.race([/* ... */]),
Promise.race([/* ... */]),
Promise.race([/* ... */]),
Promise.race([/* ... */]),
Promise.race([/* ... */]),
Promise.race([
// level 3
Promise.race([/* ... */]),
Promise.race([/* ... */])
])
])
])
— " " , . " " , . ,
const Name = fraction('John')
const User = fractal(async function* () {
while (true) {
yield `User ${yield* Name}`
}
})
const Title = fraction('Hello')
const Post = fractal(async function* () {
while (true) {
delay(5000) // -
yield `Post ${yield* Title}`
}
})
const App = fractal(async function* () {
while (true) {
console.log(`App | ${yield* User} | ${yield* Post}`)
yield
}
})
live(App)
//> 'App | User John | Post Hello'
Name.use('Barry')
Title.use('Bye')
//> 'App | User Barry | Post Hello'
// 5
//> 'App | User Barry | Post Bye'
Name Title, User Post , User , App Post — App , Post . App , Post . , "" .
. , . tmp(data), yield.
— "". , -, .
import { fractal, tmp } from '@fract/core'
const User = fractal(async function* () {
yield tmp('Loading...')
delay(5000) // -
while (true) {
yield `User John`
}
})
const App = fractal(async function* () {
while (true) {
console.log(yield* User)
yield
}
})
live(App)
//> 'Loading...'
// 5
//> 'User John'
User "", , .. - . , User 'Loading...' , , .. yield tmp(...) , .
— , , -
import { fractal, tmp } from '@fract/core'
const Timer = fractal(async function* () {
let i = 0
while (true) {
yield tmp(i++)
await new Promise((r) => setTimeout(r, 1000))
}
})
const App = fractal(async function* () {
while (true) {
console.log(yield* Timer)
yield
}
})
live(App)
//> 0
//> 1
//> 2
//> ...
Timer i , i, 1 . — , , .use(data), .
, . , — .
newEditor, , . Manager, ProfileId .
function newEditor(id) {
return fractal(async function* () {
const { name } = await loadUserInfo(id)
const Name = fraction(name)
while (true) {
// -
//
yield <input
placeholder="Input name"
value={yield* Name}
onChange={(e) => Name.use(e.target.value)}
/>
}
})
}
const ProfileId = fraction(1)
const Manager = fractal(async function* () {
while (true) {
const id = yield* ProfileId
const Editor = newEditor(id)
yield Editor // <-- Editor
}
})
const App = fractal(async function* () {
while (true) {
yield yield* Manager
}
})
- , - , Name. while(true) App, Manager. Editor, .

Manager ProfileId. Manager , Editor .
, — ProfileId - , Editor, id . .
const ProfileId = fraction(1)
const Manager = fractal(async function* () {
let lastProfileId
let Editor
while (true) {
const id = yield* ProfileId
if (id !== lastProfileId) {
lastProfileId = id
Editor = newEditor(id)
}
yield yield* Editor
}
})
, .
const BarryName = fractal(async function* () {
while (true) yield 'Barry'
})
const Name = fraction('John')
const App = fractal(async function* () {
while (true) {
console.log(yield* Name)
yield
}
})
live(App)
//> 'John'
Name.use(BarryName)
//> 'Barry'
— , yield BarryName.
, , . , . .
import { factor } from '@fract/core'
const API_VERSION = factor('v2') // 'v2' | 'v3'
// ^^^^
/* */
yield* API_VERSION('v3') //
yield* API_VERSION // 'v3' -
yield* API_VERSION.is('v3') // boolean -
//
// c
yield* API_VERSION()
yield* API_VERSION // 'v2'
, . , api API_VERSION api .
const Page = fractal(async function* () {
const apiVersion = yield* API_VERSION
while (true) {
yield `Work on api "${apiVersion}"`
}
})
const Modern = fractal(async function* () {
yield* API_VERSION('v3')
// api v3
while (true) {
yield yield* Page
}
})
const Legacy = fractal(async function* () {
yield* API_VERSION('v2')
// api v2
while (true) {
yield yield* Page
}
})
const App = fractal(async function* () {
while (true) {
console.log(`
Modern: ${yield* Modern}
Legacy: ${yield* Legacy}
`)
yield
}
})
live(App)
/*
> `
Modern: Work on api "v3"
Legacy: Work on api "v2"
`
*/
! , , ,
const Top = fractal(async function* () {
yield* API_VERSION('v3')
while (true) {
yield yield* Middle
}
})
const Middle = fractal(async function* () {
yield* API_VERSION // 'v3' - Top
yield* API_VERSION('v2') // ,
yield* API_VERSION // 'v3'
while (true) {
yield yield* Bottom
}
})
const Bottom = fractal(async function* () {
yield* API_VERSION // 'v2' - Middle
while (true) {
yield /*...*/
}
})— , . , , , .
const APP_STORE = 'APP'
function newApp({ name = 'Hello world' } /* AppState {name: string} */) {
const Name = fraction(name)
return fractal(async function* App() {
while (true) {
switch (yield* MODE) {
case 'asString':
yield `App ${yield* Name}`
continue
case 'asData':
yield { name: yield* Name } // as AppState {name: string}
continue
}
}
})
}
const Dispatcher = fractal(async function* () {
//
const data = JSON.parse(localStorage.getItem(APP_STORE) || '{}')
//
const App = newApp(data)
// 'asString'
const AsString = fractal(async function* () {
yield* MODE('asString')
while (true) yield yield* App
})
// 'asData'
const AsData = fractal(async function* () {
yield* MODE('asData')
while (true) yield yield* App
})
while (true) {
const asString = yield* AsString //
const asData = yield* AsData //
//
console.log(asString)
//
localStorage.setItem(APP_STORE, JSON.stringify(asData))
yield
}
})
: App MODE, AsString AsData, Dispatcher. , — , .

( ). — , , — , . — , . , , api ..
MV* MVVM MVP
, MV* MVVM MVP .. . , ,

— , , — .
javascript , , .
import { fractal, factor } from '@fract/core'
// app.js
export const API_URI = factor()
export const THEME = factor('light')
export const App = fractal(async function* () {
const apiUri = yield* API_URI
const theme = yield* THEME
if (!apiUri) {
//
throw new Error('Factor API_URI is not defined')
}
while (true) {
/*...*/
}
})
, .
code splitting
, await. , " " . — , js , . , ...
, . , ,

, , , (). , , , — , — , .
, , webpack, ,
// ./user.js
export const User = fractal(async function* () {
while (true) yield `User John`
})
// ./app.js
export const App = fractal(async function* () {
// ,
const { User } = await import('./user')
while (true) yield `User ${yield* User}`
})
, , , IntelliSense .
, , TodoMVC. , , … — , , , . - — . , — . - , , , , . ...
. , , , , , , , — . , , .
, . , . react styled-components — , , .
- Todos —
- Loadable — , , ,
yield tmp(...), , , - Factors — . , . .
- Antistress — , , . , , . — , — , — . ,
- ,
-
jsx -> html,react, ,diff, - — ? , , ,
-
grahpql, - -yield* gql'...' - open source — ,
- :) , — readme
, - noname- , , , , .
, , - , - react- , @fract/react-alive
import { fractal } from '@fract/core'
import { Alive } from '@fract/react-alive'
const App = fractal(async function* () {
while (true) {
yield <div>Hello world</div>
}
})
function Render() {
return <Alive target={App} />
}
— , , yield*? @fract/browser-pathname. , window.location.pathname, redirect(p: string) . , , , -.
— . , , . , react , , , , — .
, , . , .
, .
" — " ©