
不,我没有病。至少这就是我头脑中的声音。我是吸毒者。我已经努力了15年以上。我用尽了很多,直到我晕倒为止。我的观点是,最近我还没有为我的朋友,妻子或孩子感到羞耻……两个孩子!我不喜欢badazhenny,我喜欢干净,没有杂质。这些年来,我做了很多尝试,但是最近我停止寻找了。意识到同一件事让你既痛苦又快乐,这很有趣。我想去治疗,我什至想,我什至知道哪一个。您知道在您继续使用但受到监督的地方吗?
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 , , , , — .
- github
- npm
- examples
- examples sources
, , . , .
, .
" — " ©