Handle data after http get request in angular - ajax

I have a service that requests data from a get method, I'd like to map the response to an object storing some Ids and use those Ids to make other http requests.
I was told this isn't usually done in a callback manner, I looked at this How do I return the response from an asynchronous call? but I don't think it's the usual way to implement services, any hints are very appreciated.
Tried adding in onInit/constructor method in angular to be sure the object was filled before other methods were called without success.
#Injectable ()
export class ContactService {
storeIds;
getIds(callback: Function) {
this.http.get<any>(IdsUrl, Config.options).subscribe(res => {
callback(response);
});
getIds(res => {
this.storeIds = {
profileId: res.profile,
refIds: res.refIds
}
}
)
// this.storeIds returns undefined as it's an async call
this.http.post<any>(WebserviceUrl + this.storeIds.profileId , data, headers )
// .....Many other web services that relay on this Ids
}

Just create another service called StoreIdsService. Update the response you get from your first api call 'getIds' in the StoreIdsService. The idea is to have StoreIdsService as singleton service to keep state of your storeIds. You can inject StoreIdsService in anywhere component you want to get the storeIds.
Its one of manyways to share data in angular between components.
Please refer to this answer someone has posted.
How do I share data between components in Angular 2?

You can simply assign the service response to the storeIds property inside the subscribe method. and call the subsequent services inside it if you need.
#Injectable ()
export class ContactService {
storeIds;
getIds() {
this.http.get<any>(IdsUrl, Config.options).subscribe(res => {
this.storeIds = {
profileId: response.profile,
refIds: response.refIds
}
this.otherapicall1();
this.otherapicall2();
});
}

Related

NestJS handle HttpModule errors

NestJS has the following example for using their HttpModule:
#Injectable()
export class CatsService {
constructor(private readonly httpService: HttpService) {}
findAll(): Observable<AxiosResponse<Cat[]>> {
return this.httpService.get('http://localhost:3000/cats');
}
}
My question is, how does the client code (most likely a Controller) handle this response? How does it treat Observables so that Cat[] may be accessed. Or what if the Http request throws an error such as a 404.
How does a NestJS client (Controller) in this case interact with the findAll() method provided by the service?
I am not too familiar with NestJs, but if you want to run an observable http request generally you do the following to consume and catchError
this.catService.findAll().pipe(
// axio wraps the result in data
map(res=>res.data),
catchError(e=>{
...handle error 404
return of(e)
})).subscribe()
If, for whatever reason, the URL you provide to the HttpService returns a 404, that error will propagate back through the service, to the controller, and eventually to the client that called the original URL. Under the hood, NestJS will subscribe to all returned Observables so that you don't need to worry about it, you can just return the call directly from your Controller. So in the example above, say we have a controller that looks like this:
#Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
#Get()
findAllCats(): Observable<Cat[]> {
return this.catsService.findAll();
}
}
And CatsService looks like this
#Injectable()
export class CatsService {
constructor(private readonly httpService: HttpService) {}
findAll(): Observable<Cat[]> {
return this.httpService.get('http://localhost:3000/cats');
}
}
Assuming you are calling off to another server (i.e. this server is not running on port 3000) and /cats is not a valid endpoint and that server returns a 404 to you, the httpService's response will bubble up through the CatsService to the CatsController where NestJS will handle the subscription, and send the response back to the client. If you are looking to do some custom error handling, that will need to be handled in a different way. A great way to test how the HttpService responds to things is to create a simple endpoint and call off to a bad URL (like https://google.com/item which is a 404)

How to route ASP.Net Core api return value to appropriate observable based on data type returned

I have created an ASP.NET Core Web Api backend with an Angular 7 frontend. One of the methods in the Api can return either an object or an array to an Angular service. How do I route to specific observable, based on the data type returned? I am a noob to Angular, so any kind assistance would be appreciated.
Angular service call to Api:
getLinksFromSitus(situs: any) {
this.http.post(this.baseUrl + 'getLinksFromSitus', situs).subscribe(data =>
this.apiData.next(data)
);
}
Portion of Web Api that returns array if more than one APN present:
// if more than one item in list, get status information for each and return list to user to select appropriate apn
if (propApn.Count > 1)
{
return Ok(propApn);
}
Portion of same method to return object if only one value for APN:
var resultsModel = new Results
{
ArcGisLink = arcGisLink,
HistInfoLink = histInfoLink,
PropInfoLink = propInfoLink
};
return Ok(resultsModel);
You can't do this. Typescript can only type things based on static analysis at build time, what your describing would require Typescript to know the result of your API call at build time, which it doesn't do.
The best you can do is indicating that your API call can return both of your them:
public myApiFunc(req: MyRequestModel): Observable<any>
But that will still require you to figure out which type returned at runtime.
I was able to find a solution that worked...
getLinksFromSitus(situs: any) {
this.http.post(this.baseUrl + 'getLinksFromSitus', situs).subscribe(data => {
if (data.hasOwnProperty('arcGisLink')) {
this.apiData.next(data);
} else {
let vals = [];
vals = this.apiPropApn.getValue();
const item = vals.concat(data);
this.apiPropApn.next(item);
}
});
}
So, after subscribing to the HttpResponse, I am able to check if the data in the response contains a known property. If it doesn't contain the known property, then it concatenates the data to a BehaviorSubject array. It works perfectly.

Does promise object always need callback function?

I have a requirement that I need to create a service in Angular 1 and load data with an API call which can be accessed in controllers. I earlier tried by making a API call with $http service and assigning the data to the variable / object. I then injected the service and assigned the variable / object to the controller scope variable / object.
What I observed in the controller event loop is not same as service event loop and controller scope variable / object remains undefined. Later I got a solution to work by returning a promise from the service, and calling the promise in the controller, however I'm new to promises and not able to fully absorb that when I called a promise, I had to pass the function as argument which I think is a callback for the $http API call, but I'm uncertain how it's working under the hood. Can someone explain it?
//service code
this.getuserimages = function(uname) {
console.log("Username in UserImage Service: " + uname);
var promise = $http.get('/api/images/' + uname).then(function(response) {
this.userimages = response.data;
return this.userimages;
});
return promise;
}
// controller code
var userimagespromise = userImageService.getuserimages($routeParams.username);
userimagespromise.then(function(data) {
$scope.userimages = data;
Your code is a Promise chain.
I rewrited your code in a way that this chain is more clear, but the meaning is exactly the same:
$http.get('/api/images/' + uname)
.then(function(response) {
this.userimages = response.data;
return this.userimages;
})
.then(function(images) {
$scope.userimages = images;
});
You can read this flow in this way:
Please get me user images
And then, we they will be available (=> returned from the get and passed to the then function), save them in a variable and return them to the next element of the chain
And then, we they will be available (=> return from the previous promise), set them in the $scope
Please note that the entire flow is asynchronous because every Promise is "an object representing the eventual completion or failure of an asynchronous operation".
You can find more information in the Promise documentation.

Apollo Server - parse REST result in Connector, Resolver or Model

I am wrapping an older REST API service with an Apollo server. Calls to the REST service results in a JSON object that nests the payload 2 to 3 levels deep. For example:
{
- MRData: {
- CatTable : {
- Cats : []
And to further complicate matters, the nesting pattern and node names are different for each resource endpoint. So my question is, since each resource result will need custom manipulation, where is the best place to do it: in the Connector, Resolver or Model.
Connector
If done in the Connector, then a custom method is needed for each resource. Seems like a lot of boilerplate.
public fetchCats(resource: string) {
return new Promise<any>((resolve, reject) => {
request.get(url, (err, resp, body) => {
err ? reject(err) : resolve(JSON.parse(body).MRData.CatTable.Cats)
})
})
}
Resolver
The resolver method receives a promise but the result cannot be manipulated:
const allCats = (_, params, context) => context.cat.getCats()
.then((data) => { // to late to manipulate data here })
Model
The Model looks promising but not quite sure how to structure it:
public getCats() {
const cats = this.connector.fetchCats('/cats.json');
return cats;
}
Apollo will be (more often than not) integrated with REST API's. I'm looking forward discovering the best way to handle this case.
I would generally recommend doing the parsing in the connector, because they should abstract over the details of the backends. If connectors abstract over the backend, you should technically be able to switch out one backend for another when appropriate. For example you could switch from querying a REST API to sending queries directly to the database where it makes sense.
The consequence of this is that you'll need to build a new connector for every REST API, because no two REST APIs are the same.

Multiple AJAX requests with React Redux

I want to make requests to two different APIs. I then need to organize that data. I'm using redux-promise.
Currently, I have a function, calls two other functions that do the AJAX request:
export function fetchEstimates(input) {
let firstRequest = fetchFirstRequest(input);
let secondRequest = fetchFirstRequest(input);
return {
type: FETCH_DATA,
payload: {
firstRequest: firstRequest
secondRequest: secondRequest
}
}
}
Unfortunately, by putting both requests in an object, I can't seem to access the results.
export default function(state = [], action) {
switch (action.type) {
case FETCH_DATA:
// console.log(action.firstRequest);
// console.log(action.secondRequest);
return result;
}
return state;
}
As I toggle the object in dev tools, I come to this:
[[PromiseStatus]]:"resolved"
[[PromiseValue]]:Object
I can continue to toggle the options, but I can't seem to access them in my code.
If in my payload, I just return this
payload: firstRequest
I don't have issues. But of course, I need both requests. Any ideas. What is a good approach to handle this?
If you look at the source for redux-promise, you'll see that it assumes you've provided a promise as the "payload" field in your action. You're instead providing an object with two promises as sub-fields under "payload". I'm assuming that you're really interested in having both promises resolve, and then passing both results to the reducer. You'd want to use Promise.all to create a new promise that receives the results of both original promises as an argument, then use that promise as your payload. The reducer would then receive something like: {type : "DATA_RECEIVED", payload : [response1, response2]}.
You need some sort of middleware to deal with Promises (like redux-thunk), and wrap the promises in Promise.all to wait until they're both resolved. Let me know if you need a code example.

Resources