Nest js promise interceptor - rxjs

Is there a way for me to wrap a request in nest js inside a callback?
I'm trying to create a prisma transaction interceptor but the problem is that nest js interceptor requires an obserable as return type.
In order to achieve my goal I need to wrap my request in a callback like:
await prisma.$transaction(async p => {
await requestToBeFinished()
})
But all nest js provides me is an observable like
return next
.handle()
.pipe(
tap(() => {console.log('After execution')}),
);
Is there a solution to this?
Thanks

Related

How do I remove socket listeners from RTK custom middleware after the middleware has run?

How do I stop listening for socket events in my RTK custom middleware or remove the listeners until the action I am checking for is dispatched again then I add the listener again? I'm currently doing this but I don't know if this is the best approach. My code looks something like this:
export const getMessageSocketMiddleware = ({ dispatch }) => (next) => (action) => {
if (messageApi.endpoints.send.matchFulfilled(action)) {
recieveMessage.listen((data) => {
dispatch(actions.updateMessage(data))
recieveMessage.disconnect();
})
}
return next(action);
};
If I don't disconnect inside the callback, every new message received gets duplicated. This isn't an event that fires all the time so I'll like to add a toast notification. Is it ok if I do that inside the middleware, or should I create a new listener inside my react component to handle that?

RxJS Observable on Axios how to get access to the Response

I am working on getting a response from an HTTP POST in my NestJS project. I am using the HttpModule which wraps Observables from RxJS around Axios. here's some code:
async doSomething(bar: Bar) {
const resp = await this.httpService
.post(`${UPLOAD_URL}?app_token=111222333`, {
foo: bar
})
.pipe(map(response => response))
.toPromise()
.catch(err => {
this.logger.error(err)
})
this.logger.debug('response object')
this.logger.debug(resp)
}
In this particular case, I just want to see what the result of the resp object is. I'm getting a Converting circular structure to JSON error, though. So my question is, how would I view the response? I am okay with viewing it with the .toPromise() chain or without it. I'm not familiar with Observables so I convert it to a Promise. Not sure if that's a huge perf hit, but it isn't important for this question.
The map you are using is not helpful, as it does not actually do any mapping of the response. If you are wanting to log something in the observable without changing it you can use the tap operator and do something like
this.httpService().post(url, data).pipe(
tap((data) => console.log(data),
).toPromise()
the reason you are getting the Converting circular structure to JSON error is because the Nest Logger will JSON.stringify() objects and does not use a circular replacer. Consider stringifying the object yourself with a circular replacer, using console.log() or using a different logging library.

Using NGRX in a Route Resolver

I am using Angular 6.
I am also using NGRX Store.
I am using a route guard to make sure the user is logged in to the application.
I then use a resolver to get the initial user profile, then place it in the NGRX store.
I am new to NGRX and I am not sure if this is the correct way to write the resolver.
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): any {
return this.loginService.getLoginData()
.pipe(
map((result:UserData) => {
this.store.dispatch(new userActions.SetLoginData(result));
this.loginService.getDropdownData(
result.userId,
result.countryCode,
).subscribe( data => {
this.store.dispatch(new userActions.SetDropdownData(data));
})
})
)
}
I am also not sure if this is the correct way to do the RXJS.
any suggestions,
Thanks
I'm going to point you to Preloading ngrx/store with Route Guards, an article of Todd Motto which explains it really well.
There is also an example of the guard in the NgRx example app
#Injectable()
export class CoursesGuard implements CanActivate {
constructor(private store: Store<CoursesState>) {}
getFromStoreOrAPI(): Observable<any> {
return this.store
.select(getCoursesState)
.do((data: any) => {
if (!data.courses.length) {
this.store.dispatch(new Courses.CoursesGet());
}
})
.filter((data: any) => data.courses.length)
.take(1);
}
canActivate(): Observable<boolean> {
return this.getFromStoreOrAPI()
.switchMap(() => of(true))
.catch(() => of(false));
}
}
First of all I think it would make sense to seperate the authentication check and the data resolution into separate classes. For authentication it makes more sense to use a CanActivate guard. See: https://angular.io/api/router/CanActivate
With this out of the way your resolver can focus on only getting the data that is actually required. Here you need to be aware that if you return an observable in your resolver, the observable needs to complete in order for the resolver to complete. The problem is that if you select something from the store, the resulting observable never completes, hence your resolver will never finish resolving your data. You can work around this fact by using the first() or take(1) operator. timdeschryvers answer has a nice example on how to accomplish that.

ReduxObservable cancellation based on action type and its data

I have React app which uses redux-observable with typescript. In this scenario, FetchAttribute Action gets triggered with a id and then make an ajax call.
In certain case, I would want to cancel the ajax request if "FETCH_ATTRIBUTE_CANCEL" action was triggered with the same id as of "FetchAttributeAction" action.
action$.ofType(FETCH_ATTRIBUTE)
.switchMap((request: FetchAttributeAction) => {
return ajax.getJSON(`/api/fetch-attribute?id=${request.id}`)
.flatMap((fetchUrl) => {
// return new action
})
.takeUntil(action$.ofType(FETCH_ATTRIBUTE_CANCEL));
});
interface FetchAttributeAction{
id: number;
}
Problem:
How do we cancel the execution based on action type + action data?
In my case, it would FETCH_ATTRIBUTE_CANCEL and id.
The key is to filter actions in the takeUntil notifier to only those which match the ID you care about.
action$.ofType(FETCH_ATTRIBUTE_CANCEL).filter(action => action.id === request.id)
So here's what it might look like:
Demo: https://stackblitz.com/edit/redux-observable-playground-xztkoo?file=fetchAttribute.js
const fetchAttributeEpic = action$ =>
action$.ofType(FETCH_ATTRIBUTE)
.mergeMap(request =>
ajax.getJSON(`/api/fetch-attribute?id=${request.id}`)
.map(response => fetchAttributeFulfilled(response))
.takeUntil(
action$.ofType(FETCH_ATTRIBUTE_CANCEL).filter(action => action.id === request.id)
)
);
You can also take a look at previous questions:
Redux Observable: If the same action is dispatched multiple times, how do I cancel one of them?
Independent chain cancellation in redux-observable?
Dispatch an action in response to cancellation
The OP also pointed out that they were using switchMap (as did I originally when I copied their code) which would have meant that the epic only ever had one getJSON at a time since switchMap will unsubscribe from previous inner Observables. So that also needed to be chained. Good catch!
I think you should be able to make takeUntil selective for a certain action id with pluck and filter.
ex:
.takeUntil(action%.ofType(FETCH_ATTRIBUTE_CANCEL)
.pluck('id')
.filter((cancelActionID) => cancelActionID === fetchID))
The non-obvious part to me is how to get the current fetchID to run that comparison. I might consider try using do to store in a temporary variable

Azure Mobile Client, how to do a bulk insert in Angular 4?

I am current using the js library:
<script src="//zumo.blob.core.windows.net/sdk/azure-mobile-apps-client.2.0.0.js"></script>
And I am currently trying to do a bulk insert instead of foreach. Is there any method call, that I can use?
addSubjectSpecialization(specialization): Promise<any>{
var orderTable = this.client.getTable("specialization");
return new Promise((resolve, reject) => {
orderTable.insert(specialization).then((res) => {
resolve(res);
}, (err) => reject(err))
})
}
In my component I am doing a foreach, to insert multiple objects. Is there any better way? That means: Instead of foreach, do we have a function for bulk insert?
Ref: https://learn.microsoft.com/en-us/azure/app-service-mobile/app-service-mobile-html-how-to-use-client-library#inserting
Note: I have seen the suggestions provided by Stackoverflow. And none solves the issue. The suggestions where MobileClient(.Net) has tableStorage bulk insert. And I am not sure how can I do it in typescript.
Currently, there is no function we can use for bulk insert. But you may post a feature request on this Github repository.

Resources