Giter Club home page Giter Club logo

Comments (18)

cesarandreu avatar cesarandreu commented on August 20, 2024

I'm pretty interested. Currently I'm using a plugin that I wrote to overwrite context.executeAction. I think it's mostly backwards compatible; I think the only case where it's not backwards compatible is when you're using the arguments object.

I've been abusing co and generators, so feel free to ignore that part. From my actions I could just export co.wrap(action) instead to achieve the same goal.

action-plugin.js

var co = require('co'),
  debug = require('debug'),
  log = debug('ActionPlugin'),
  isPromise = require('is-promise'),
  isGeneratorFunction = require('is-generator-function')

module.exports = function ActionPlugin () {
  return {
    name: 'ActionPlugin',
    plugContext
  }
}

function plugContext (opts, context) {
  context.executeAction = executeAction.bind(context)

  return {
    plugComponentContext,
    plugActionContext
  }

  function plugActionContext (actionContext) {
    actionContext.executeAction = context.executeAction
  }

  function plugComponentContext (componentContext) {
    componentContext.executeAction = componentContextAction
  }

  function componentContextAction (action, payload) {
    context.executeAction(action, payload).catch(err => {
      context.executeAction(context._app._componentActionHandler, {err}, () => {})
    })
  }
}

function executeAction (action, payload={}, done) {
  log(`Executing action ${action.displayName || action.name} with payload ${payload}`)

  var promise
  if (isGeneratorFunction(action)) {
    promise = co(action(this.getActionContext(), payload))
  } else {
    promise = new Promise((resolve, reject) => {
      var result = action(this.getActionContext(), payload, (e, r) => e ? reject(e) : resolve(r))
      if (isPromise(result)) {
        result.then(resolve, reject)
      } else if (action.length < 3) {
        resolve(result)
      }
    })
  }

  if (done)
    promise.then(result => done(null, result)).catch(err => done(err))

  return promise
}

If it's a generator function, call the action with action context and payload, and pass it to co.
Otherwise call the action with action context, payload, and a callback inside of a promise. If a promise is returned then wait for that. If it has less than three params assume its sync, and resolve with the returned value. If the the action has 3 params then it will have received the callback, which will also resolve the promise. Finally, if the action has less than 3 params and it throws, I think the promise will catch it and it'll get rejected.

If execute action got called with a third param, it'll also call done. One of the nice perk of using promises is that you don't have to worry about releasing zalgo.

Would you be interested in a PR or did you have a different approach in mind?

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

Yes, we'll absolutely take a PR.

I'm not a big fan of adding co as a dependency though, so maybe we leave that part out for now.

from fluxible.

cesarandreu avatar cesarandreu commented on August 20, 2024

Oh, definitely. co is too opinionated for something like this, I think just supporting promises is fine.

Should it use the global Promise and assume that anyone that's using this will either polyfill it or replace it with their own preferred implementation?

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

Good question. For now let's use Bluebird. Once we start using babel to compile Fluxible for ES6, we will be able to drop that dependency.

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

Hi @cesarandreu we've migrated the docs over to this repo so if you want to add some documentation we can get this merged.

from fluxible.

quicksnap avatar quicksnap commented on August 20, 2024

👍 👍 👍 👍 =)

from fluxible.

cesarandreu avatar cesarandreu commented on August 20, 2024

I'll try to write up the docs tonight, thanks! :D

from fluxible.

igorbt avatar igorbt commented on August 20, 2024

IMHO, having callbacks and/or promises in actions is breaking Flux unidirectional data flow. According to a Facebook developer post:

  1. Actions don't have callbacks, as they are by design fire-and-forget.

Why Fluxible did this "correction"?

from fluxible.

jedireza avatar jedireza commented on August 20, 2024

@igorbt your observation is correct. In order to render server-side, we need to know when the page is ready to render. And we do that with callbacks. However, we do keep the flux flow with actions fired from the componentContext (from your React views)... those are still fire-and-forget (no callbacks).

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

@igorbt There is a description of what @jedireza mentioned in the Components documentation.

from fluxible.

igorbt avatar igorbt commented on August 20, 2024

Thanks, @jedireza , @mridgway ! I understand now. It would be nice to see this explanation in the Actions documentation also.
Btw, is it legit to pass parameters in the action callback function then? I was tempted to do so, but if the only purpose of the callback is to know when to render, then it probably would be wrong.

from fluxible.

cesarandreu avatar cesarandreu commented on August 20, 2024

Haven't had a chance to update the docs yet.

@igorbt:
In my PR, the action promise will be resolved with the callback value e.g. done(null, value), the returned promise's resolve value e.g. return Promise.resolve(value) , or if the action function has length below 3, it'll resolve the action promise with the returned value, e.g. return value

I think triggering actions inside of actions is fine as long as you make sure to wait for them in your parent action.

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

@igorbt Good call out. I added more information to the actions doc.

from fluxible.

igorbt avatar igorbt commented on August 20, 2024

I'm just starting to explore Flux and Fluxible and the thing with calling another action from an action just doesn't feel right for me. I re-read the original Facebook Flux description but didn't find anything for or against this practice. I didn't find anywhere else some strong opinion about that.

If Action1 calls Action2 and then dispatch Payload1, and in the same time Action2 dispatches Payload2, if feels like cascading updates. But Flux is trying to minimize that!
The thing seems to me even worst when Action2 returns Payload2 as value (in callback or promise) and Action1 then uses Payload2 to construct Payload1. Then Payload1 is derived data. It seems more like a Store responsibility.

from fluxible.

quicksnap avatar quicksnap commented on August 20, 2024

While the actions may be asynchronous, there's nothing wrong with nearly-simultaneous dispatches--the stores should handle events and their payloads discretely, only being concerned with potentially waiting for other stores to handle an event first (using waitFor).

This isn't cascading, only asynchronous. It would be cascading if the stores were to trigger an action, or a component doing so without any user interaction.

Does that clarify at all? (Disclaimer: I do not work on Fluxible)

from fluxible.

quicksnap avatar quicksnap commented on August 20, 2024

Furthermore, IMO it's very helpful for actions to set up other actions on intervals, for situations like polling.

from fluxible.

cesarandreu avatar cesarandreu commented on August 20, 2024

Updated my PR with docs!

from fluxible.

mridgway avatar mridgway commented on August 20, 2024

Awesome! I'll check it out soon.

from fluxible.

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.