カラクリスタ

「輝かしい青春」なんて失かった人のブログ

たった 64 行で Node.js v6.6.0 で動く非同期 Redux っぽいのできたぞ!!1

"use strict";

function createMapper(validate) {
const uid   = Date.now().toString() + '+' + Math.random().toString();
const get   = (state) => { return ( typeof(state [[uid]] ) !== 'undefined' ) ? state [[uid]]  : null };
const map   = (state, value)  => { let v = {}; v [[uid]]  = value; return Object.assign({}, state, v) };

const from    = (state) => {
const value = get(state);
const err   = validate(value);
return ( err === null ) ? Promise.resolve(value) : Promise.reject(err) ;
};

const create  = (state, value) => {
const err = validate(value);
return ( err === null ) ? Promise.resolve(map(state, value)) : Promise.reject(err) ;
};

return { from: from, create: create };
}

function createDispatcher(initialState, handle) {
const once = (fn, ms) => {
let t; t = setTimeout(() => { fn(); clearTimeout(t); t = null }, ms);
};

const apply = (state) => {
let snapshot = Object.assign({}, state);
once(() => { handle(null, snapshot); snapshot = null }, 0);
return Promise.resolve(state);
};

let queues = [];

const update = (p1) => {
while (queues.length !== 0) {
const task = queues.shift();
p1 = p1.then((state) => { return task(state) }, (err) => { handle(err, null) });
}

return p1.then((state) => { return apply(state) }, (err) => { handle(err, null) });
};

let loop; loop = (p1, sleep) => {
once(() => { loop( (sleep ? p1 : update(p1)), queues.length === 0 ) }, 15);
};

loop(Promise.resolve(initialState), false);

return (action) => { queues.push(action) };
}

(() => {
const validater   = (x) => { return typeof(x) === 'number' ? null : new TypeError('this is not number') };
const count       = createMapper(validater);
const onSnapshot  = (err, state) => { ( err !== null ) ? console.warn(err) : console.log(state) };
const dispatch    = createDispatcher(count.create({}, 0), onSnapshot);

const action      = (state) => { return count.from(state).then((x) => { return count.create(state, x + 1) }) };

setInterval(() => { dispatch(action) }, 1000);
setInterval(() => { dispatch(action) }, 2000);
})();

本日の成果です。見納めください。

ちなみにこれ、

たった 64 行で Node.js v6.6.0 で動く非同期 Redux っぽいのできたぞ!!1

ってタイトルで言ってますが、 Redux っぽい感じ、という事を、僕が本当に飲み込めているかどうかには疑問があるため、 JavaScript 界隈で詳しい人の批評、待ってます。

という事で、こちらからは以上です。


追記: 2018-02-05

この記事を書いた当初、

たった 64 行で Node.js v6.6.0 で動く非同期 Flux っぽいのできたぞ!!1

と言っていたのですが、実際には Flux じゃなくて Redux じゃね?と思ったので、本文とタイトルを修正しました。