dependabot[bot] on npm_and_yarn
dependabot[bot] on npm_and_yarn
Bump nodemailer from 2.7.2 to 6… (compare)
dependabot[bot] on npm_and_yarn
Bump moment from 2.24.0 to 2.29… (compare)
dependabot[bot] on npm_and_yarn
Bump moment in /angular4-Bootst… (compare)
dependabot[bot] on npm_and_yarn
dependabot[bot] on npm_and_yarn
Bump karma from 4.0.1 to 6.3.16… (compare)
dependabot[bot] on npm_and_yarn
Good day, everyone. I cannot find the "old" rocket launcher example where I thought I would find an answer. Here is the question:
when a timer is counting we have to re-render the timer in a view, where should nap
go in the example?
state.render = function(model) {
state.representation(model)
state.nextAction(model) ;
}
In the example above render
is inside state.representation(model)
and if place nap
check there to, thennap
and nextAction
could run "simultaneously".
Is this valid approach:
const sr = stateRepresentation( model )
if ( nap( sr ) ) return
render( sr )
nextAction( model )
So if nap
is true, there is no render
, if nextAction
is needed, then it is done only after render
https://github.com/jdubray/sam-samples/blob/master/inferno-rocket/index.html#L251-L255
Revisiting the above with more clarity-
Of couse a SAM "machine" only has 1 NAP function, but my project is an "cart engine" (ecommerce) that supports modular extension. Modules have an interest in implementing their own NAPs against the cart state.
The top level NAP therefore delegates responsibility to registered modules, invoking each of their NAP implementations. In effect these modules are collaborating without knowing anything about each other, but you can't just compose their actions.
This would be no problem if they only need to respond to the current state- It is only when they start to care about the "event" that led to the state change, that things become problematic. The event can be captured by the SAM machine and rendered into the current state. e.g. "itemAdded".
Child NAPs can respond to that, but of course a new cycle begins with each action, meaning the next time round, it would not be "itemAdded" anymore, and the 2nd NAP missed its chance to act.
Rocket launcher is simple because when countdown gets to 0, you stop. It's a terminating condition. But think about counting upwards, and needing something to trigger only after, when "count > 20". You need to synthesise an event like "count exceeded 20", otherwise it'll trigger in an infinite loop.
So going back to my problem - to solve the "multiple proposed actions", actions can only be queued. But from my own reading (not sure if SAM or Lamport papers) it seems like a fundamental principle that intents are strongly associated with the state from which they are raised, to the point where it seems legitimate to require a "version/sequence number" on an intent, and to reject it if the model version has changed since then.
If I start queing actions however, I break that principle... actions become deferred to be applied against future unknown states and that doesn't feel right! But I did come up with a pattern which I think addresses the problem in my use case, and would be interested to hear thoughts.
I change the wiring so that a NAP returns model proposal(s) AND a "defferedApplication" callback.
The idea is that you can define a secondary predicate, evaluated against the new state when the action is about to be applied - to determine whether it is still valid or not. i.e. return true or false.
If the change (a.k.a. Event) that caused a NAP to propose an action was "Item added to shopping cart", the "deferredApplicatoin" callback would potentially evaluate that the product was still present in the cart.
Andrew Ray updated his blog design and tweeted about it so I revisited and found this Flux pattern post (dated Nov. 13 2021, but I recall seeing it circa 2014). Have to say, understanding the SAM pattern helped me understand Flux (without Redux) this time around.
https://andrewray.me/blog/the-mental-model-that-helped-me-finally-understand-flux