dispatch ngxs action in switchMap ignoring the return value - ngxs

There must be a standard way to solve this, but I haven't found anything yet. I am probably not phrasing my search correctly.
I have a search input field and as is good practice, I use the switchmap operator to cancel previous http requests, when the user keeps typing.
I have based this off the example in the ngxs documentation:
this.actions$
.pipe(
ofActionDispatched(SomeAction),
debounceTime(2000),
distinctUntilChanged(),
untilDestroyed(this),
switchMap(() => {
return this.store.dispatch(new SomeOtherAction());
})
).subscribe(() => {
});
SomeAction is dispatched every time the user types something in the input field and saves in in the store (that's why SomeOtherAction has not constructor parameter).
Is there a better way to do this without having this empty subscribe block? This looks like an anti-pattern.

Another way you could consider is to only dispatch the action to change the searchText in the state after you debounce etc.
Using the valueChanges Observable on the search input form control you could pipe through a debounce/distinct/filter or whatever combination suits your purposes before calling store.dispatch with your action to modifiy the state.
Then you'd only modify the state the minimum required times rather than each key press and could also call the HTTP request from there (and I don't think you'd need the action stream subscription in the component).
Doco for Angular Form valueChanges here

Related

Angular: await for query string parameter but do something else if it doesn't appear

I have tried to formulate a question title the most generic way that applies to my problem.
I have an Angular application where I have to handle authentication over an external requirement: either use a query string parameter token that has to be exchanged with the server for a JWT, or try to search for a JWT refresh token in the local storage.
It is:
First test the query string: if there is a queryString parameter token, grab the token, delete any JWT in the local storage, exchange the token via API for two JWTs (id_token and refresh_token)
Else go for the refresh token: if there is a refresh_token in the local storage available, exchange it for a JWT id_token via API
Else, if none of the two are available, the user is unauthenticated and a prompt should be displayed
I used Observables almost the correct way
this.queryParamMap$.unsubscribe();
this.queryParamMap$ = this.activatedRoute.queryParamMap
.subscribe(
params => {
let token = params.get('token');
........
if (!!token) {
doLoginWithToken();
else if (isJwtRefreshAvailable())
doLoginWithRefreshToken();
There is one problem with this approach: the very first time the application starts up, the query param map is empty, even if I follow a direct browser link http://localhost:4200?token=AAAAAAAA. I have to wait for the next element which contains the token.
This has two undesirable effects:
At the first attempt, being the token undefined, the application immediately tries to log in with the refresh token
If I filter the queryParamMap observable for a token being present, if a token is never present the observable will never emit, thus not activating the subscription.
My problem can be summarized/generalized as follows.
I have an Observable that I know for sure emits undefined the very first time, but either in no time it could be ready with a proper value, or it won't emit new values after the initial undefined.
Else said, while the observable emits undefined and my code starts reacting to it (e.g. by testing for token), a new value can be ready for emission right away.
How can I solve this in Rxjs? Note that accessing the JWT token from the local storage is a synchronous operation, but it's easy to create Observable.of(localStorage.get(KEY)) which emits immediately if a refresh token is present.
For that, I can't realistically use race operator, because the refresh token is always ready and always wins the race.
How can I write asynchronous code that performs like the steps I described earlier?
As the ultimate result of the authentication, an Observable<UserProfileDto | undefined> emits the information about the user, which is used to display personalized information.
You have 2 problems here:
On init you got "undefined" value (its because probably, under the hood, there is some BehaviourSubject emitting its default value). To overcome this, you can add RxJS operator (skip(1)) to skip that first value, but:
Problem here is if you do not have query values at all, you will not reach your subscribe function. Its because queryParamMap will emit a value only, if there is a change (and in that case there is not):
You can do it without Angular, to just parse url from:
const urlParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlParams.entries());
Or using router in Angular:
this.router.events
// Wait for the navigation end event (since component is initialized before angular router navigation is done)
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe((event: NavigationStart) => {
// Take query params snaphot
const map = this.route.snapshot.queryParams;
});

How to get the result of a asynchronous action in NGXS?

I want to perform an action based to the result of an asynchronous NGXS action.
In a Angular frontend app I'm using NGXS for state management. Some of the actions involve talking to a backend via REST calls. Those actions are implemented as asynchronous actions, with the reducer functions in my state classes returning an Observable.
What I'm looking for is a way to get hands on the result of the backend call, to be able to perform some action.
One use case I'm trying to implement is navigation to just created objects: Business objects are created in the frontend (Angular) app with a couple of domain properties. They get persisted in the backend, and as a result an ID for this object is created and returned to the frontend, and incorporated into the NGXS store. As a direct response to this, I'd like to navigate to a detail view for the new object. To do so, I need
(a) the information that the call has been returned successful, and
(b) the answer from the backend (the ID in this case).
Another slightly more complicated use case is the assignment of a number of tags to an business object. The tags are entities by themselfes, and have an ID each. In the UI, the user can either pick existing or add new tags. Either way, multiple tags can be added in a single step in the UI, which means I have to
call the backend for each new tag to create the ID
after all missing tags are created, update the business object with the list of tag IDs
In general, there are use cases in the frontend that depend on the result of a backend call, and there is no clean way to find this result in the store (although it's in there)
I know I can subscribe to the Observable returned from the store's dispatch method (as shown in asynchronous actions).
I also know about action handlers. In both cases I can attach code to the event of an action finished, but neither option enables me to get the result of the backend call. In the fist case, the Observable carries the whole store, while in the latter case I get the original Action, which is unfortunately missing the essential information (the ID).
The part you're missing here are selectors. Dispatching actions is not supposed to give you back a result. The only purpose of the Observable returned by store.dispatch() is to tell you when the action's handlers are done.
To get to the data returned by your calls to the backend, you have to patch the state inside your action handler. And then, outside of your state, you can access the data using store.select() or store.selectSnapshot() depending on what you need. Your state class should look somewhat like this (untested):
#State()
export class SampleState {
#Selector(SampleState)
sampleSelector(state) {
return state.sampleObject;
}
#Action(SampleAction)
sampleAction(ctx: StateContext<any>, action: sampleAction) {
return sampleBackendCall(/* ... */).pipe(
tap((result) => {
ctx.patchState({ sampleObject: result });
})
);
}
}
Now you can access this result where ever you need using the Store. For the use case of navigating to an element after its creation, you can combine a subscription to store.dispatch() with a store.selectSnapshot() like this:
store.dispatch(new SampleAction()).subscribe(() => {
navigateTo(store.selectSnapshot(SampleState.sampleSelector));
});
Note that in this easy case a selectSnapshot is perfectly fine, as we only want to get the value we just finished writing into the state. In most cases though, you will want to use store.select() or the #Select() decorator because they return Observables which enable you to also correctly display changes in your state.
That said, I'd like to add that if saving data inside the state is not necessary for you at all, then probably NGXS is the wrong library for you in the first place and you could as well just use an ordinary angular service directly returning the result of the backend call, like suggested in the comments.

How to distinguish koa ctx is multipart/form-data type or not?

So i'm using koa2,
if this request is multipart type, believe i need to process
ctx.request.body.fields
otherwise i process
ctx.request.body
So what's the best way to distinguish and handle these 2 cases ?
I guess my point of view is, if you're needing to check for a form submission as well as other activity, then perhaps your endpoint is doing a bit much? It very much depends on your use case of course, but keeping form data and other content types separate may be a clearer API.
Having said that, I don't see any reason to get more complicated than checking for the presence of fields. koa-body is a great way to go about this.
One thing you might like to consider is using the middleware stack to your advantage. For example, only do stuff if there's a form submission but allow other actions to take place:
router.post('/', koaBody({ multipart: true }),
async (ctx, next) => {
if (ctx.request.body.fields) {
// Handle form if present
}
await next() // Pass control down the stack
}
))

What's the difference between Promise and AJAX?

Both promises and AJAX calls are asynchronous operations. A GET/POST request could be made with both. << Edit: that's a WRONG statement
So what's the difference between them? And when would be best to use one instead of the other?
Also, one more thing:
Recently I encountered a promise which had an AJAX in its body. Why put an async operation inside an async operation? That's like putting a bread loaf in a bread sandwich.
function threadsGet() {
return new Promise((resolve, reject) => {
$.getJSON('api/threads')
.done(resolve)
.fail(reject);
})
}
jQuery is used here. And the AJAX call has Promise behavior and properties. I didn't get that earlier but here are my thoughts:
We can do something in the Promise. Then use the AJAX call and in the done function pass the resolved Promise logic. Specifically in this example there is none.
Now I see that I had confused both. They're pretty much 2 different things. Just because they're asynchronous, doesn't mean they're interchangeable.
==============
EDIT 2: Just some materials I found useful:
Promise Anti-Patterns
You are confused about promises and Ajax calls. They are kind of like apples and knives. You can cut an apple with knife and the knife is a tool that can be applied to an apple, but the two are very different things.
Promises are a tool for managing asynchronous operations. They keep track of when asynchronous operations complete and what their results are and let you coordinate that completion and those results (including error conditions) with other code or other asynchronous operations. They aren't actually asynchronous operations in themselves. An Ajax call is a specific asynchronous operation that can be used with with a traditional callback interface or wrapped in a promise interface.
So what's the difference between them? And when would be best to use
one instead of the other?
An Ajax call is a specific type of asynchronous operation. You can make an Ajax call either with a traditional callback using the XMLHttpRequest interface or you can make an Ajax call (in modern browsers), using a promise with the fetch() interface.
Recently I encountered a promise which had an AJAX in its body. Why
put an async operation inside an async operation? That's like putting
a bread loaf in a bread sandwich.
You didn't show the specific code you were talking about, but sometimes you want to start async operation 1 and then when that async operation is done, you want to them start async operation 2 (often using the results of the first one). In that case, you will typically nest one inside the other.
Your code example here:
function threadsGet() {
return new Promise((resolve, reject) => {
$.getJSON('api/threads')
.done(resolve)
.fail(reject);
})
}
is considered a promise anti-pattern. There's no reason to create a new promise here because $.getJSON() already returns a promise which you can return. You can just do this instead:
function threadsGet() {
return $.getJSON('api/threads');
}
Or, if you want to "cast" the somewhat non-standard jQuery promise to a standard promise, you can do this:
function threadsGet() {
return Promise.resolve($.getJSON('api/threads'));
}

Redux ajax workflow with prelogic

I'm writing a restful redux/react app.
My desired output is such.
INPUT_CHANGE-->
(state = {valid: false})->REDUCER->(state = {valid: true})-->
AJAX CALL
From the redux documentation, async javacript is supposed to be called from the action creator, but I don't understand how to get to the action creator once the state changes from valid:false to valid:true.
Since this is a react app, I could change a hidden input called valid, which has an onChange action creator attached to it, but this seems like an unneccessary extra step. Any ideas?
My general preference is to have the action creators handle all async operations. So the validation operation in this question is comparable to the shouldFetchPosts function in http://rackt.org/redux/docs/advanced/AsyncActions.html
The action creator would then be something like inputChangeAndSubmitIfValid which corresponds to that file's fetchIfNeeded action creator.
On very rare occasions I implement an observer for catching store changes, but I always try to find a better action oriented way first.

Resources