Giter VIP home page Giter VIP logo

Comments (7)

goatslacker avatar goatslacker commented on May 22, 2024

Wow this is a little tricky since you have to deal with animations and such. Personally, I'd keep the business logic out of the stores and keep the stores as just a representation of the state of the game. You can create a special component (a view controller?) which has most of the business logic, or put all that sort of logic in a util that gets called through the action. This is probably the flux way of doing things.

Anyway, the answer to your question. The dispatcher prevents you from firing actions while an action is still in the dispatch loop and this is because you don't want to get into a code mess where firing off a single action causes a set of cascading actions to take place. This is what flux was trying to avoid with MVC in the first place.

While it's not recommended I can let you know how to do it. One way around this limitation is to move the action dispatch out of the main loop via something like setTimeout or setImmediate. In alt, there's a helper function associated with every action which lets you do this sort of thing defer.

Here's an example on using defer:

// fire a butt load of actions
MyActions.prototype.swapTile = function (tile1, tile2) {
  this.dispatch([tile1, tile2])
  this.actions.saveUndoState.defer(tile1)
  this.actions.checkBoard.defer()
  this.actions.saveGame.defer()
  this.actions.checkGameOver.defer()
}

this.actions contains all your other actions defined in this fictional MyActions.prototype. You may call defer with however many arguments as you want. Defer is just like a setImmediate

Good luck!

from alt.

philippotto avatar philippotto commented on May 22, 2024

@goatslacker Correct me, if I'm wrong, but isn't something like the following perfectly fine?

MyActions.prototype.swapTile = function (tile1, tile2) {
  this.dispatch([tile1, tile2])
  this.actions.saveUndoState();
  this.actions.checkBoard();
}

Strictly speaking, no dispatch is initiated while another one is active. Instead, the first dispatch is initiated and completed and then the second and third one are processed.

I just tested it and alt doesn't seem to prevent this sort of "action delegation". Am I missing something?

from alt.

pontifechs avatar pontifechs commented on May 22, 2024

I haven't had a chance to work on this particular side-project in depth since I created this issue, but I tried this really briefly, and this does work as I'd expect with the defer. Without the defer, the actions and their corresponding handlers in the store are called, but the store only emits one change event to the view layer. Having multiple change events to the view layer was what i was really after with this.

The defer solves most of my problem, but I'm still having trouble finding a way to coordinate which actions should be done. For example, I'd like to do something like this:

MyActions.prototype.swapTile = function (tile1, tile2) {
  this.dispatch([tile1, tile2]);
  this.actions.checkBoard.defer();    // Clears a single 3-in-a-row, and somehow magically
                                      // writes out this clearedLastCheck condition
  while(clearedLastCheck)
  {
    this.actions.checkBoard.defer();
  }
}

Unfortunately I have no idea how checkBoard might tell this function what clearedLastCheck should be each iteration.

Luckily, with the way some of the game logic in my clone works out, I can always say that a cascade won't be longer than 13. It's not a great solution, but I can just call checkBoard 13 times.

All in all, not being able to do this sort of thing seems to be one of the explicit design goals behind flux. So I don't really have a problem with needing to abuse the framework to try and get it to do something it was designed not to do.

from alt.

philippotto avatar philippotto commented on May 22, 2024

Without the defer, the actions and their corresponding handlers in the store are called, but the store only emits one change event to the view layer.

That is weird, because when I tested it (and I just retested it), every dispatch call resulted in a change event in the view. If this was not the case, I would have thought that this was a bug in alt.

Maybe the reason for the problem is somewhere else? But I'm glad you found a workaround.

@goatslacker I would be happy to hear some clarification regarding the multiple dispatches and the view events, since I'm just starting to use alt and want to do it right.

from alt.

goatslacker avatar goatslacker commented on May 22, 2024

@philippotto good catch, this wasn't working before.

Here's a proper broken example that needs the defer

var Alt = require('alt')

var alt = new Alt()

function MyActions() {
  this.generateActions('gameover', 'saveUndoState')
}

MyActions.prototype.checkBoard = function () {
  console.log('checking the board')

  if (true) {
    this.actions.gameover()
  }
}

MyActions.prototype.swapTile = function (tile1, tile2) {
  this.dispatch([tile1, tile2])

  // This is ok to do:
//  this.actions.saveUndoState(tile2, tile1)
//  this.actions.checkBoard()
}

var TileActions = alt.createActions(MyActions)

function TileStoreSpec() {
  this.bindActions(TileActions)
  this.board = [2, 1]
  this.undo = null
}
TileStoreSpec.prototype.swapTile = function (x) {
  this.board = x

  // Needs defer:
  TileActions.saveUndoState(x[1], x[0])
  TileActions.checkBoard()
}
TileStoreSpec.prototype.saveUndoState = function (x) {
  this.undo = x
}
TileStoreSpec.prototype.gameover = function () {
  this.board = null
}

var TileStore = alt.createStore(TileStoreSpec)

TileStore.listen(function () {
  console.log('Changed', TileStore.getState())
})

TileActions.swapTile(1, 2)

from alt.

philippotto avatar philippotto commented on May 22, 2024

@goatslacker Thank you, totally makes sense, now!

from alt.

goatslacker avatar goatslacker commented on May 22, 2024

@pontifechs @philippotto thank you both for posting

from alt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.