I have seen three different patterns for this and the alt docs do not make the distinction clear. If I have an action, how should I go about calling dispatch? Here are the three ways I have seen:
1. The action returns a function, which `dispatch` is passed into.
addPayment(args) {
return (dispatch) => {
dispatch();
// other action code
};
}
2. The action calls this.dispatch.
addPayment(args) {
this.dispatch();
// other action code
}
3. The action does not call dispatch.
addPayment(args) {
// other action code
}
It is not clear to me what difference there is between these three options, and it is especially unclear to me whether option #3 calls dispatch at all.
The bindActions method seems to associate actions with action handlers, so it would kind of make sense that a given action handler should be called automatically when the associated action is called, which would result in code that looked like option #3. But then, why would we ever need to explicitly call dispatch?
There is no tag for alt, so....yeah. Tagging it flux since that's the closest match.
Okay, as I understand things, approach #2 was patched out in later releases of alt and will now cause an error.
Approach #1 works fine when you want to trigger dispatch before your action completes. It's generally used when you have a handler that initiates a loading state in the UI, so you want to set things to loading while your action completes. Then you have separate success/failure actions (often just generated via alt's generateActions) with their own handlers which take care of what happens after the action completes.
Approach #3 is for when you want to trigger dispatch after your action completes. Here's a key bit from the alt docs that I missed:
You can also simply return a value from an action to dispatch.
So simply returning a value will call dispatch, and thus your action completes first. The docs also hasten to add:
There are two exceptions to this, however:
Returning false or undefined (or omitting return altogether) will not dispatch the action
Returning a Promise will not dispatch the action
So that bit provides a way to avoid triggering dispatch at all.
Related
I've recently started migrating from ngrx to ngxs and had a design question of where I should be placing some of my calls.
In NGRX, I would create 3 actions for each interaction with an api. Something like:
GetEntities - to indicate that the initial api call was made
GetEntitiesSuccess - to indicate a successful return of the data
GetEntitiesFail - to indicate a unsuccessful return of the data
I would create an effect to watch for the GetEntities Action that actually called the API and handled the response by either calling the Success/Fail actions with the resultant payload.
In NGXS, do I make the api call from the store itself when the action occurs or is there some other NGXS object that I am supposed to use to handle those API calls and then handle the actions the same way I did in ngrx (by creating multiple actions per call)?
Most of the examples I have seen, and how I have used it is to make the API call from the action handler in the state, then when the API returns patch the state immediately.
Then after the patch call, you can dispatch an action to indicate success/failure if you need to. Something like this:
#Action(GetSomeData)
loadData({ patchState, dispatch}: StateContext<MyDataModel>, {payload}: GetSomeData) {
return this.myDataService.get(payload.id)
.pipe(
tap((data) => {
patchState({ data: data});
// optionally dispatch here
dispatch(new GetDataSuccess());
})
);
}
This q/a might also be useful Ngxs - Actions/state to load data from backend
I'm new in Flux/React Native.
I'm quite confused about dispatch vs emit using in Flux.
What is the main difference between them? And what happen when I use same Action Type in dispatch and emit.
For example:
Dispatcher.dispatch({
actionType: 'ACTION1'
});
SomeStore.emit('ACTION1');
In Flux, events are emitted by the store indicating a change in its state. This 'change' event is listened to by views. This will prompt a view to fetch new state from the store. Mind you, the event never contains payload / information about the new state. It is really just what it reads - an event.
Actions are slightly different. While they are indeed events, they are things that occur in our domain eg., Add item to cart. And they carry a payload that contains information about the action, eg.,
{
id: ‘add-item-to-cart’,
payload: {
cartId: 123,
itemId: 1234,
name: ‘Box of chocolates’,
quantity: 1
}
}
Actions are 'dispatched' from the views and the store(s) responds to the dispatch by possibly changing its state and emitting a 'change' event.
So basically:
A view dispatches an action with a payload (usually due to a user interaction) via the dispatcher
The store (which had previously registered itself with the dispatcher)
is notified of the action and uses the payload to change its state and emit an event.
The view (which had previously registered itself with the store) is notified of the change event which causes it to get the new state from the store and change itself.
So that's the difference. And about the question "use same Action Type in dispatch and emit", it doesn't really make sense, does it?
I suggest you read this blog post - http://blog.andrewray.me/flux-for-stupid-people/ (The title means no offence BTW :))
You already know this, but I'll say it again: A unidirectional data flow is central to the Flux pattern. That means data (not control) always flows in one direction.
I presume this is a basic mistake, but as my searches made no effect, let's do it here anyway :)
I have a function returning a promise, but it runs so fast (because code is almost empty) that when .then() is called, it is too late and no event is called.
The reason why it happens is because that's a dummy code (for testing), so, the Promise concept is applied because of a situation where an actual async request is done.
So, is there a way to call the resolve/reject functions even after the function was processed? Or I would have to use lazy promises?
Update: I tried RSVP.defer() but didn't like its approach as it's not intuitive enough (requires some workaround to set .then() and .catch(), etc.
I have a function returning a promise, but it runs so fast (because code is almost empty) that when .then() is called, it is too late and no event is called.
That does not matter even one bit. Well behaved promises (like native promises, and virtually every library except old jQuery) are built with a guarantee that no matter when you attach the then handler - it will call the handler (and it will always do so asynchronously). A promise is just a value + time.
RSVP passes a suite of over 1000 tests to ensure this is always the case.
var p = Promise.resolve(); // create empty, already resolved promise
setTimeout(function(){
p.then(function(){
// will always be called, eventually.
});
}, 1000000 + Math.random() * 10000000);
I am new to angular and want to use it to send data to my app's backend. In several occasions, I have to make several http post calls that should either all succeed or all fail. This is the scenario that's causing me a headache: given two http post calls, what if one call succeeds, but the other fails? This will lead to inconsistencies in the database. I want to know if there's a way to cancel the succeeding calls if at least one call has failed. Thanks!
Without knowing more about your specific situation I would urge you to use the promise error handling if you are not already doing so. There's only one situation that I know you can cancel a promise that has been sent is by using the timeout option in the $http(look at this SO post), but you can definitely prevent future requests. What happens when you make a $http call is that it returns a promise object(look at $q here). What this does is it returns two methods that you can chain on your $http request called success and failure so it looks like $http.success({...stuff...}).error({...more stuff..}). So if you do have error handling in each of these scenarios and you get a .error, dont make the next call.
You can cancel the next requests in the chain, but the previous ones have already been sent. You need to provide the necessary backend functionality to reverse them.
If every step is dependent on the other and causes changes in your database, it might be better to do the whole process in the backend, triggered by a single "POST" request. I think it is easier to model this process synchronously, and that is easier to do in the server than in the client.
However, if you must do the post requests in the client side, you could define each request step as a separate function, and chain them via then(successCallback, errorCallback) (Nice video example here: https://egghead.io/lessons/angularjs-chained-promises).
In your case, at each step you can check if the previous one failed an take action to reverse it by using the error callback of then:
var firstStep = function(initialData){
return $http.post('/some/url', data).then(function(dataFromServer){
// Do something with the data
return {
dataNeededByNextStep: processedData,
dataNeededToReverseThisStep: moreData
}
});
};
var secondStep = function(dataFromPreviousStep){
return $http.post('/some/other/url', data).then(function(dataFromServer){
// Do something with the data
return {
dataNeededByNextStep: processedData,
dataNeededToReverseThisStep: moreData
}
}, function(){
// On error
reversePreviousStep(dataFromPreviousStep.dataNeededToReverseThisStep);
});
};
var thirdFunction = function(){ ... };
...
firstFunction(initialData).then(secondFunction)
.then(thirdFunction)
...
If any of the steps in the chain fails, it's promise would fail, and next steps will not be executed.
Say I have a screen like this:
<screen>
<button label="Foo" name="foo-button"/>
<action:behaviors>
<action:when widget-event="foo-button.onClick">
<action:call-ajax-workflow name="ajax/do-lots-of-foo"/>
<!-- (1) -->
<action:call-ajax-workflow name="ajax/do-less-foo"/>
<!-- (2) -->
</action:when>
<action:when system-event="onAjaxRequestCompleted">
<!-- (3) -->
</action:when>
</action:behaviors>
</screen>
What is the correct place to put a handler for each AJAX request? Theoretically, I would assume that either (1) or (2) would be incorrect, as if the workflows are truly asynchronous then ajax/do-less-foo should return before ajax/do-lots-of-foo.
My instinct is to handle the responses at location (3), and conditionally execute different code based on the value of event-parameters.workflow.
Is this correct? Or is call-ajax-workflow actually blocking, and the commands in the onClick block are just executed serially?
Currently, call-ajax-workflow does block the timeline it's running in while the call is happening. It doesn't block the screen or any other timelines.
In Aviarc 2, you could call an ajax workflow from script to have it non-blocking. I'm not sure whether this capability is still easily accessible in Aviarc 3 (presumably it is).
Handlers should currently be placed inline so that they're next to the code they're handling, or, if a handler should deal with multiple calls, it should be put into an action block with calls to said action block as inline handlers.
The onAjaxRequestCompleted event should only ever be bound to if there's something which needs to be done indiscriminately on returns from ajax calls.
If the command is ever changed to be (possibly) non-blocking, or if an additional command is added which is non-blocking, or so forth, I would expect that handlers would be addable as sub-elements of the command.