Where to make API call and how to structure actions - ngxs

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

Related

FireAndForget call to WebApi from Azure Function

I want to be able to call an HTTP endpoint (that I own) from an Azure Function at the end of the Azure Function request.
I do not need to know the result of the request
If there is a problem in the HTTP endpoint that is called I will log it there
I do not want to hold up the return to the client calling the initial Azure Function
Offloading the call of the secondary WebApi onto a background job queue is considered overkill for this requirement
Do I simply call HttpClient.PutAsync without an await?
I realise that the dependencies I have used up until the point that the call is made may well not be available when the call returns. Is there a safe way to check if they are?
My answer may cause some controversy but, you can always start a background task and execute it that way.
For anyone reading this answer, this is far from recommended. The OP has been very clear that they don't care about exceptions or understanding what sort of result the request is returning ...
Task.Run(async () =>
{
using (var httpClient = new HttpClient())
{
await httpClient.PutAsync(...);
}
});
If you want to ensure that the call has fired, it may be worth waiting for a second or two after the call is made to ensure it's actually on it's way.
await Task.Delay(1000);
If you're worried about dependencies in the call, be sure to construct your payload (i.e. serialise it, etc.) external to the Task.Run, basically, minimise any work the background task does.

Different ways to call dispatch in Alt.js?

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.

Which lifecycle hook should I make requests and immediately setState?

When my component mount I need to request it content from an API. In the docs:
componentDidMount() is invoked immediately after a component is
mounted. Initialization that requires DOM nodes should go here. If you
need to load data from a remote endpoint, this is a good place to
instantiate the network request.
and it follows:
Calling setState() in this method will trigger an extra rendering (...)
Use this pattern with caution
because it often causes performance issues.
What is the best practice to make a request to an API and, immediately, setState with the response?
The best way to call an API and update the state after you receive the response is in componentDidMount() or componentWillMount().
Which one might depend on what you want to do with your data from your API-call. If you need to access your components DOM then componentDidMount() must be used. That said, neither of these will save you from an additional re-render, unless your data doesn't need to be set to your state, in which case you can just save it to this.
The official documentation even states this, in this section:
componentDidMount() is invoked immediately after a component is mounted. Initialization that requires DOM nodes should go here. If you need to load data from a remote endpoint, this is a good place to instantiate the network request.
Before Rendering to call api:
componentWillMount(){
fetch(api)
.then((response)=>{
this.setState({data:response.data});
})
}
After Rendering to call api:
componentDidMount(){
fetch(api)
.then((response)=>{
this.setState({data:response.data});
})}
Before Rendering to call props data:
componentWillReceiveProps(){
this.setState({data:this.props.data});
}
Whenever you trigger setState your component is going to be re-rendered (regardless the lifecycle event).
Use this pattern with caution...
You can get to an endless loop for example if you trigger setState in componentWillReceiveProps and you are not taking care of future props correctly.
My suggestion is to stick with componentDidMount and set state as soon as your api request is fulfilled:
componentDidMount() {
fetch('api-endpoint')
.then(response => response.json())
.then(result => this.setState({ stateProp: result }))
}

How to handle server/request errors in flux?

I've called an action creator from a component to create/edit a resource, which in turn sends an API request to a server. How should I handle cases where the server is down, or returns an error? I want any relevant components to be notified of the success/failure.
My current ideas are to:
Dispatch COMMENT_FAILED, COMMENT_SUCCESS actions to the comment store, which then notifies the components somehow?
Use promises within the initiating component to catch errors from the action call and respond/render them appropriately.
Which is better? Why?
This has been previously asked in React+Flux: Notify View/Component that action has failed?, but the only proposed solution is to use Promises as in 2. I can certainly do that, but it seems... un-Flux-like.
What I usually do is create an error reducer specific to my container/component. For instance, if the user filed a login I would dispatch the error to my login reducer as follows.
export default function dispatchError() {
return function(dispatch) {
dispatch({
type: 'LOGIN_ERROR',
payload: 'You entered an incorrect password'
});
}
}
Now in your instance this would be very similar. Anytime there is a failed request dispatch to your reducer.

Angular.JS multiple $http post: canceling if one fails

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.

Resources