0

    let drawer = {};
    let stacks = {};
    
    async function actionDealCard(hidden) {
    
        let previousMutation = drawer.mutation;
        drawer.mutation = true;
    
        await new Promise(resolve => {
            setTimeout(resolve, previousMutation?500:100);
            console.log('animation happening');
        });
        stacks.mutation = hidden;
    }
    
    async function mainFunction() {
        let deals = [1,2,3];
        for (let key in deals) {
            await actionDealCard(key);
        }
        console.log(stacks, drawer);
    }

mainFunction();

Above is the simplified version of my code. I implemented this using imperative coding style. Now I want to turn this into reactive streams. How do I do that?

I've tried something like this:

// I need an event stream that describes when to mutate drawer
// to pass to DrawerProperty function
// This might be a bus to simplify the solution but buses are bad.
let esDrawerMutate = ???

let drawer = DrawerProperty(esDrawerMutate);

async function actionDealCard(key) {
  // I have no clue what's going on here
}


let deals = Bacon.fromArray([1,2,3]);

let esMain = deals.flatMap(key => {
    return Bacon.fromPromise(actionDealCard(key));
});

esMain.log();

function DrawerProperty(esMutate) {
    return Bacon.update({},
        [esMutate, _ => _.mutation = true]);
}

function StacksProperty(esMutate) {
    return Bacon.update({},
        [esMutate, _ => _.mutation = true]);
}

When my above code run this is the output:

animation happening
animation happening
animation happening
{
  "mutation": "2"
} {
  "mutation": true
}

I guess my goal here is to produce this same output in functional style.

eguneys
  • 6,028
  • 7
  • 31
  • 63
  • are you set on using Bacon? – richytong Jun 09 '20 at 23:34
  • Yes I am using Bacon, but any other solution might give me a clue. – eguneys Jun 09 '20 at 23:39
  • It's hard for me to follow what you want to do, would you care to show more of your imperative code? – richytong Jun 09 '20 at 23:51
  • This is a deal action in a card game. `drawer` is mutated to show one less card in the drawn cards, then promise is an animation happening, after the animation is done, stacks is mutated to add one card to the stack. – eguneys Jun 09 '20 at 23:57
  • `userSelectsStack` waiting for user input looks like a brittle part of your system. Is there an event you could attach `actionSelectStack`? – richytong Jun 10 '20 at 01:37
  • But this is a drag drop thing see the middle of the code where I also wait for the drop event to happen. On user events I resolve these promises that I wait for in this function. – eguneys Jun 10 '20 at 01:43

1 Answers1

0

I went off your comment for this one mostly, please let me know if anything needs clarification. I'm using some methods from a library of mine. pipe just chains functions together and waits for them if they're async, tap will call the function you pass it and disregard the output, returning the input

const drawer = { cards: [1, 2, 3], did_mutate: false }

const popCardFromDrawer = () => drawer.cards.pop()

const animate = () => {
  console.log('animation happening')
  const animationTime = drawer.did_mutate ? 100 : 500
  drawer.did_mutate = true
  return new Promise(resolve => setTimeout(resolve, animationTime))
}

const stacks = { cards: [] }

const addCardToStacks = card => { stacks.cards.push(card); return stacks }

const { pipe, tap } = rubico

const dealAction = pipe([
  popCardFromDrawer, // () => card
  tap(animate), // card => card
  addCardToStacks, // card => stacks
])

const main = async () => {
  while (drawer.cards.length > 0) {
    await dealAction()
    console.log('drawer', drawer, 'stacks', stacks)
  }
}

main()
<script src="https://unpkg.com/rubico/index.js"></script>
richytong
  • 2,387
  • 1
  • 10
  • 21
  • I've edited my question to reflect my reasoning on wanting reactive streams. Currently my code pretty much looks like yours. – eguneys Jun 10 '20 at 01:24