I did a small project here on pure JS and during this I needed to work with the Rest API. Well, not with XMLHttpRequest handles to pull, I decided, for sure there are countless ready-made solutions for such a simple task? ..
As you can guess from the KDPV, I was somewhat mistaken; however, first things first. But if in brief - it turned out such a pretty bike , with which requests to the Rest API are obtained, as promised in the title, compact and beautiful.
So, I needed a Java API client for the Rest API. Google issued a bit of libraries - restful.js , rest , amygdala . Actually, there was another such library, but this is a jQuery plugin. jQuery in the project is not used and drag it somehow did not want to; but, in part, I liked the syntax offered by the library and it will still pop up later.
Amygdala disappeared immediately - no Promise, which means no async / await. Its functionality bounds are also strange, amygdala rather claims something like an under-data-layer; about the absence of a downgraded version and unnecessary dependencies, I tactfully keep silent.
There are two candidates left - restful.js and rest.
rest offers a kind of minimal core and gives ample opportunities for its customization with the help of so-called "interceptors" - interceptors in the original. I don’t know how cool it is - the prospect of building full URLs and indicating the method with my hands with each request didn’t tempt me at all, there were no interceptors for modifying this behavior, and the documentation didn’t delight. I switched to the last option - restful.js.
RESTful resources. Think Restangular without Angular.
Actually, I prefer Ember, but what's the difference? The main thing is that it was convenient to use!
const articleCollection = api.all('articles'); // http://api.example.com/articles // http://api.example.com/articles/1 api.one('articles', 1).get().then((response) => { const articleEntity = response.body(); // if the server response was { id: 1, title: 'test', body: 'hello' } const article = articleEntity.data(); article.title; // returns `test` article.body; // returns `hello` // You can also edit it article.title = 'test2'; // Finally you can easily update it or delete it articleEntity.save(); // will perform a PUT request articleEntity.delete(); // will perform a DELETE request }, (response) => { // The reponse code is not >= 200 and < 400 throw new Error('Invalid response'); });
This is an example from the documentation . It looks good in comparison with competitors, and the documentation is quite intelligible ... There are no options anyway. Take? We take.
There is such a concept of "reasonable silence", which implies, if you retell in your own words that the solution of a certain problem is sharpened, conditionally, under 90% of user cases, and in the remaining 10% you need to explicitly say that there are special circumstances.
A trivial example of this concept is the default settings in most programming languages.
Much less trivial example (which is, nevertheless, just a generalization of the previous one) - optimization of any interface based on the expected behavior of the user, be it a command, graphic, software or physical interface: switches there, buttons and other hardware twirls.
The overall strategy of these optimizations is the same - 90% of users must take as few actions as possible to achieve their goals. It would not be a great exaggeration to say that this is the general formula for progress - the invention of more and more simple, in terms of the number of necessary movements, interfaces for solving all the same tasks.
And, in general, these most reasonable defaults are one of the main ways to simplify.
Why do I play Captain Obvious, spreading over the head of a tree? Because the next bike is just another bike, but a bike with a philosophical base under it is no longer just another bike, but can even be seen from afar on a motorcycle!
The end of a small lyrical digression.
So restful.js. I used it extremely briefly - and a couple of days did not pass, as I understood that:
Each time, it is not cool to call all () explicitly.
let games = api.all('games'); //<-- games.get(); //... games.post();
API resources are what underlie the whole frontend, so how are they created manually each time? These are the things that should be sewn into the fabric of the project. api.games.get(); api.games.post()
api.games.get(); api.games.post()
- it looks much better (yes, it was just the influence of the syntax of that library on jQuery). However, it was still possible to get around, we are dynamic boyars: api.games = api.all('games');
Manually expanding the response and entity is not cool at all!
let games = (await api.games.get()).body().data(); //<-- that sucks
My eyes would not see, fingers would not write; but I had to. Here those interceptors from rest would be useful, there the functionality of deploying a raw response to an object is just implemented. Restful.js also has interceptors, but here they are more modest, not that.
Uncaught (in promise) TypeError: _temp.body(...).data is not a function
. Be kind, use forEach, defined as a method on the entity, which is returned by body () on response, which is returned by getAll ().In general, a classic example of an uncomfortable interface. I don’t know if it’s the influence of an angulyar, which seems to be famous for its academic character, or it’s more about orientation by the framework rather than the library, but I didn’t like the interface offered restful.js much. In fact, according to the result, I liked it, probably even less than the interface of competitors - apparently, the effect of an ominous valley affects: close to the ideal, but not reached, and from love to hate only one bike.
I threw restful.js and threw two classes, which in 150 lines of code did in principle the same as restful.js for 6000 (six thousand, this is not a typo ).
Then I thought, put it on github , refactored, mastered the webpack (great stuff!), Mocha + chai, sinon and travis, laid it out on npm and bower, wrote the documentation, wrote an example and finally wrote this article to make life easier for those who encounter with the same problem.
At the moment (June 2016) there are not enough tests, there are no HEAD and OPTIONS methods, it is difficult to get a raw answer and too few badges in the README (only one, what a shame! ..).
However, this is all easy to fix. The main thing is that another-rest-client provides a clear and simple interface that I like working with; I hope that not only me.
Using the github API:
var api = new RestClient('https://api.github.com'); api.res({repos: 'releases'}); api.repos('Amareis/another-rest-client').releases('latest').get().then(function(release){ console.log(release); document.write('Latest release of another-rest-client:<br>'); document.write('Published at: ' + release.published_at + '<br>'); document.write('Tag: ' + release.tag_name + '<br>'); });
Investments? Easily:
var api = new RestClient('http://example.com/api/v1'); api.res({ //or it gets object and returns object where resource is available by name dogs: [ 'toys', 'friends'], cats: 0, humans: 'posts' }); /* last string is equal to: api.res('dogs').res(['toys', 'friends']); api.res('cats'); api.res('humans').res('posts'); */ api.dogs(1337).toys.get(); //GET http://example.com/api/v1/dogs/1337/toys api.dogs(1337).friends(2).delete(); //DELETE http://example.com/api/v1/dogs/1337/friends/2 //POST http://example.com/api/v1/humans/me/posts, body="{"site":"habrahabr.ru","nick":"Amareis"}" api.humans('me').posts.post({site: 'habrahabr.ru', nick: 'Amareis'});
With async / await, the code is much more fun:
var me = api.humans('me'); var i = await me.get(); console.log(i); //just object, ie {id: 1, name: 'Amareis', profession: 'programmer'} var post = await me.posts.post({site: 'habrahabr.ru', nick: i.name}) console.log(post); //object
Thanks for attention.
Source: https://habr.com/ru/post/302288/
All Articles