1
\$\begingroup\$

I would like to know if this is the best/most efficient/industry standard way of converting from the http response to an array of typed values:

Type class:

export class University {
 public "state-province": string;
 public country: string;
 public name: string;
 constructor(state_province: string, country: string, name: string) {
 this["state-province"] = state_province;
 this.country = country;
 this.name = name;
 }
}

Here is the http request and conversion. The code in question is within the map(...) call:

const resp = this.http
 .get<University[]>(`http://universities.hipolabs.com/search?country=United+Kingdom&name=camb`)
 .pipe(map(respData => {
 const uniArr: University[] = [];
 respData.forEach(element => {
 uniArr.push(new University(element['state-province'], element.country, element.name));
 });
 return uniArr;
 }))
 .subscribe(respData => {
 console.log('Content:', respData);
 });

In C# there are many easier ways to convert the response data of the get request into an array (or list) of typed instances. Am I doing this correctly here, in Angular/RxJS?

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
asked Apr 24, 2022 at 19:33
\$\endgroup\$
0

1 Answer 1

1
+50
\$\begingroup\$

Addressing Your Main Question

I would like to know if this is the best/most efficient/industry standard way of converting from the http response to an array of typed values

Just as an array has its forEach() method it also has a map() method. That method essentially pushes the return value of the callback function into an array and returns the array. Because of this the code within the map function callback can be simplified using that method instead of calling the forEach() method.

Thus this inner block:

.pipe(map(respData => {
 const uniArr: University[] = [];
 respData.forEach(element => {
 uniArr.push(new University(element['state-province'], element.country, element.name));
 });
 return uniArr;
})

can be simplified to:

.pipe(map(respData => {
 return respData.map(element => {
 return new University(element['state-province'], element.country, element.name);
 });
})

Notice there is no need to declare the array- i.e. uniArr because the map method returns an array.

And that can be simplified because there is only a single statement being returned

.pipe(map(respData => {
 return respData.map(
 element => new University(element['state-province'], element.country, element.name)
 );
})

And the return before the call to the map method could also be removed though it might make for a long line that some would split

.pipe(map(respData => respData.map(element => new University(
 element['state-province'],
 element.country,
 element.name
))))

Using the map method approach there are no side-effects of the callback function and thus it is a pure function. This means it is simpler to test, and allows for fewer indentation levels.

1

Review

While there isn't much code to review here, the present code appears quite readable. Indentation is consistent and variables have acceptable names.

It would be wise to check respData to ensure it is an array before calling a method like forEach() or map() on it, and if the code doesn't already catch exceptions from the call to this.http.get() then it would be wise to also handle those cases. For example, what happens if the network fails or the API is not available?

answered Apr 27, 2022 at 16:14
\$\endgroup\$
1
  • \$\begingroup\$ Condensed to the max! I like it \$\endgroup\$ Commented May 25, 2022 at 6:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.