DEV Community

Cover image for A Simple Approach to Managing API Calls

A Simple Approach to Managing API Calls

Michael McShinsky on July 13, 2020

In my article, "Architecting Frontend Projects To Scale", we took a look at organizing our frontend code base in a way to make scaling and succeedi...
Collapse
 
sumukhesh profile image
Sumukhesh

Great read. As a junior developer it helped understand the importance of building scalable architecture. Its so easy to just bundle everything up in single file but it surely has long term repercussions. I have experienced it.
Cheers !!

Collapse
 
wulymammoth profile image
David • Edited

Hi Michael -- interesting post.

What is prefix in your examples? I'm unsure because prefix usually implies "placed before", but it comes after the base URL in your examples. Suffix?

Would what you've outlined here be better described as a clear separation of concerns between the data gathering and the view logic? Furthermore, the components themselves are unconcerned about how it acquires its data so long as it gets them?

I do like the provider abstraction, though! However, the downside, from what I can tell, is that it is a light wrapper around Axios. I think the methods defined there are typically a part of what I describe below that's found in your core logic. I think you're trying to enforce an interface (which is good), but the downside of this, is more providers aren't added, so whatever pattern has been established means almost nothing at all. However, if there certainly are, this idea that you're capturing is known as the strategy pattern, that often comes up for anyone that's worked with an OAuth library to offer delegated auth.

I think what you've named, ApiCore or core is akin to the repository pattern -- providing an interface to perform CRUD operations against a resource.

Collapse
 
mmcshinsky profile image
Michael McShinsky • Edited

You're right, prefix would be better changed to endpoint to make it more descriptive.

This can be considered a light wrapper to axios but can really be changed to any provider you want pretty easily.

Thanks! I appreciate your experience and feedback!

Collapse
 
wulymammoth profile image
David

An endpoint usually encompasses the entire URL. If you're up for a suggestion, mine would be resource in the canonical API and RESTful nomenclature sense. The resource that you're using as an example appears to be tasks resources.

Fair enough. If I added or created a new provider, rather than swapping/modifying existing code and possibly introducing a regression -- I'm typically for keeping legacy things around, doing a partial release to end users for something new, address any bugs, then switch over and remove the old. I like your emphasis on clean architecture which alludes me to the ideas surrounding "Clean Code" by "Uncle Bob" who is often attributed for the SOLID acronym. You may enjoy this repository: github.com/ryanmcdermott/clean-cod...

Thread Thread
 
mmcshinsky profile image
Michael McShinsky

I like resource better, thanks. Especially since this abstraction directly address the resource in question in addition to any custom endpoints related to the resource. Good catch.

Thanks for the article! Looks like a really good read. 😄

Thread Thread
 
wulymammoth profile image
David

Happy coding, Michael! And thanks for sharing. These sorts of pieces keep me in the loop in JS land that I haven't worked in for about two years :)

Thread Thread
 
himanshu2454 profile image
Himanshu Chouhan

Thanx for sharing the link David

Collapse
 
angha_ramdohokar_0b6505c2 profile image
Angha Ramdohokar

Hi Michael, this article helped me understand the abstraction layer you have added over APIs middleware.
I have implemented this in my recent project.
Thanks for sharing.
Great read.

Collapse
 
biapar profile image
BP

How to check if the api return an error or data?
Here for example:
function _createTask(task) {
apiTasks.post(task).then((res) => {
// state logic
});
}

Collapse
 
mmcshinsky profile image
Michael McShinsky

Add a .catch after your .then

Collapse
 
biapar profile image
BP

Don't work, because it goes always into the 'then' branch. I think this logic issue is caused by core.js that return the with the same instruction the good or bad value.

.getAll()
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err.code);
});

Thread Thread
 
mmcshinsky profile image
Michael McShinsky

I can't say for certain since there are various scenarios in which your code doesn't register the error as a thrown error, bad response, etc... of which I don't know what your code is.

Example: Many users assume a 4xx error response from axios should throw an error and be caught by the .catch. This is not the case unfortunately and you have to update the axios configurations to change how response codes are handled.

Thread Thread
 
biapar profile image
BP

Ok, I tried to switch off the api server and the pointer goes in the catch in the api core but the high level api get the error in the then branch. How to different the bad/good response?

Collapse
 
dyeplucban profile image
Globoy • Edited

I got an error on exporting individual api when creating a custom function.

but if directly export it, it works. I don't know what's wrong.

EXPORT ERROR

Collapse
 
mmcshinsky profile image
Michael McShinsky

You'll either want to on line 3 export const skillsApi or on line 17 export default skillsApi.

Collapse
 
kevinpallado profile image
Kevin Pallado

hi did you try to create customCall? can you show me how you done

Collapse
 
mmcshinsky profile image
Michael McShinsky

task-api-example.js has one. You can add your axios logic there.

Collapse
 
kevinpallado profile image
Kevin Pallado

can you provide any example for custom call api?

Collapse
 
mmcshinsky profile image
Michael McShinsky

task-api-example.js has one. You can add your axios logic there.

Collapse
 
xdiepx profile image
Diep Dao

what is the index.js for?

Collapse
 
mmcshinsky profile image
Michael McShinsky

A typical pattern for exporting all files within a folder instead of having a bunch of different imports is done via an index.js. You import all sibling files to this file and then export from there.

Collapse
 
xdiepx profile image
Diep Dao

Thanks, btw thanks for the tip above really helped me

Collapse
 
xdiepx profile image
Diep Dao

oh i see

Collapse
 
jeffskynird profile image
HvIvON

the best way to implement AbortController to cancel requests??, only pass as param?

Collapse
 
mmcshinsky profile image
Michael McShinsky

Yeah, you definitely could customize your api implementation to cater to that.

Collapse
 
biapar profile image
BP

Where Do you put the "header" axios config ?

Collapse
 
mmcshinsky profile image
Michael McShinsky

One option is to put it (in this example) in the provider.js file.

Collapse
 
asaduzzaman69 profile image
Asaduzzaman Himel

Great Post. I am wondering where should i put my Login and signup handler. Because they are not reusable but they are related to api functionality. Any suggestion!?

Collapse
 
mmcshinsky profile image
Michael McShinsky

Yeah, you could add them in as part of the auth (namespaced) portion of your api functionality.

Collapse
 
ram_kumar_83c84d1cee8bd92 profile image
Ram Kumar

I am getting...

undefined is not an object (evaluating '_provider.default.getSingle')

Collapse
 
mmcshinsky profile image
Michael McShinsky

Since I can't see your code, the first assumption is that an incorrect syntax in the import or implementation was made.