Skip to content

Instantly share code, notes, and snippets.

@dmitriid
Last active October 27, 2015 09:04
Show Gist options
  • Save dmitriid/baa371845e617a2dc18e to your computer and use it in GitHub Desktop.
Save dmitriid/baa371845e617a2dc18e to your computer and use it in GitHub Desktop.

The answer: it should've been .merge in button's model, not .combineLatest. Obviously

Intended behaviour:

  • click the button
  • while the request is sent, display 'Loading...'
  • when the response is received, display original button
  • there are random color changes when the button is clicked (just to see that everything works)

Problem:

Everything works until superagent encounters an error. Then everything breaks and no more requests are sent out.

Tried to catch according to https://github.com/cyclejs/cycle-http-driver/issues/8

However, this somehow broke the cycle of things:

  • The button turns into 'Loading...' and never reverts to original state

I've sprinkled some console.logs around, and here's what happens:

  • button's click is triggered and registered in the button's model (in loading$)
  • HTTP request is sent, trggers an error (in main's views catch)
  • the response is registered in the button's model (in done$)
  • For some reason Rx.Observable.combineLatest produces the result of loading$ (not of done$)

Code:

main.js

import {run} from '@cycle/core';
import {makeDOMDriver} from '@cycle/dom';
import {makeHTTPDriver} from '@cycle/http';

import main from 'components/main/index';

run(main, {
    DOM: makeDOMDriver('#app'),
    HTTP: makeHTTPDriver({autoSubscribe: true})
});

index.js

/** @jsx hJSX */
import {hJSX} from '@cycle/dom';
import Rx from 'rx';

import _ from 'lodash';

/*
 * Componens
 */

import SimpleButton from 'components/buttons/simple/index';

function getRandomColor() {
    var letters = '0123456789ABCDEF'.split('');
    var color = '#';
    for (var i = 0; i < 6; i++) {
        color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}

function view (sources){

    const httpResponse$$ = sources.HTTP;

    const httpResponse$ = httpResponse$$.flatMap(x$ => {
        return x$.catch(function(e){
            console.log('error: ', e);
            return Rx.Observable.just({text: `Error: ${e}`});
        })
    });

    const finalSources = _.merge(sources, {response$: httpResponse$.map(({text}) => text)});

    const {DOM, intent} = SimpleButton(finalSources);
    const colors$ = intent.map(() => getRandomColor());

    const VTree = Rx.Observable.combineLatest(
        colors$.startWith(''),
        DOM, (color, DOM) => <div style={{color: color}}>Click the button {DOM}</div>
    );
    const url = 'http://date.jsontest.c';

    return {
        DOM: VTree,
        HTTP: intent.map(() => url)
    }
}

export default function(sources){
    return view(sources);
};

components/buttons/simple/index

/** @jsx hJSX */
import {hJSX} from '@cycle/dom';
import Rx from 'rx';

import _ from 'lodash';

import './style.styl';

const state = {
    LOADING: 0,
    DONE: 1
};

function intent({DOM}){
    const click$ = DOM.select('#simple')
                  .events('click')
                  .map((e) => {e.stopPropagation(); return e.target;});
    return {
        click$: click$
    }
}

function model({response$}, {click$}){
    const loading$ = click$.map(() => {console.log('click'); return state.LOADING});
    const done$ = response$.map(() => {console.log('done'); return state.DONE});

    return Rx.Observable.combineLatest(loading$, done$, (s) => {console.log(s); return s});
};

function view(model$){
    const defaultDOM = <div id="simple">Btn</div>;

    return model$.map((s) => {
        if(s === state.LOADING){
            return <div>Loading</div>;
        } else {
            return defaultDOM;
        }
    }).startWith(defaultDOM);
}

export default function(sources){
    const actions = intent(sources);
    const model$ = model(sources, actions);
    const view$ = view(model$);
    return {
        DOM: view$,
        intent: actions.click$
    };
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment