JavaScriptからのRest APIのリクエストはコンパクトで美しい

ここでは純粋なJSで小さなプロジェクトを行いましたが、その間にRest APIを使用する必要がありました。 ええ、XMLHttpRequestをペンでプルしないでください。そのような単純なタスクには、おそらく無数の既製のソリューションがあります。







KDPVから推測できるように、私は多少間違えていました。 ただし、まず最初に。 要するに、ここで判明したのは 、ヘッダーで約束されているように、コンパクトで美しいREST APIへのリクエストを受信できる素晴らしいバイクです







画像







候補者



そのため、Rest API用のJavaScriptクライアントが必要でした。 Googleは、 restful.jsrestamygdalaといういくつかのライブラリを発行しました。 実際、まだそのようなライブラリがありましたが、これはjQueryプラグインです。 jQueryはプロジェクトで使用されておらず、どういうわけかドラッグしたくありませんでした。 しかし、一部には、ライブラリによって提案された構文が好きであり、これはまだ後ほど登場します。







扁桃体はすぐに姿を消しました-約束はありません。つまり、非同期/待機はありません。 また、機能の境界は奇妙であり、扁桃体は、アンダーデータ層のようなものであると主張する可能性が高い。 折りたたまれたバージョンの欠如と不必要な依存関係について、私は巧みに黙っています。

restful.jsとrestの2つの候補が残っています。







restは特定の最小限のコアを提供し、いわゆる「インターセプター」を使用してカスタマイズするための十分な機会を提供します-オリジナルのインターセプター。 これがどれほどクールかはわかりません。リクエストごとに完全なURLを作成してメソッドを指定する見込みはまったくありませんでした。この動作を変更するインターセプターもいませんでした。 最後のオプション-restful.jsに移動しました。







サーバー側のRESTfulリソースと対話するための純粋なJSクライアント。 角度のないRestangularを考えてください。


実際、私はEmberを好みますが、違いは何ですか? 主なことは、使用するのが便利であることです!







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'); });
      
      





これはドキュメントの例です。 競合他社と比較して見た目が良く、ドキュメントは非常にわかりやすいです...まだオプションはありません。 取る? 取って







わずかな余談



「合理的な沈黙」という概念があります。自分の言葉で言い直すと、特定の問題の解決は条件付きで90%未満のユーザーケースに収監され、残りの10%には特別な状況があることを明確に言う必要があります。







この概念の簡単な例は、ほとんどのプログラミング言語のデフォルト設定です。







それほどささいな例ではありません(それでも、前のものを単純に一般化したものです)は、一般的なコマンド、グラフィック、ソフトウェア、または物理インターフェイスであるかどうかにかかわらず、予想されるユーザーの動作に基づくインターフェイスの最適化です:サーキットブレーカー、ボタン、その他のハードウェアの回転







これらの最適化の全体的な戦略は同じです-ユーザーの90%は、目標を達成するためにできるだけ少ないアクションを実行する必要があります。 これが進歩の一般的な公式であると言っても過言ではありません-必要な動きの数という点でますます単純な発明、すべて同じ問題を解決するためのインターフェース。

そして、一般的に、これらの最も合理的なデフォルトは、簡素化する主な方法の1つです。







キャプテンエビデンスをプレイして、ケープをツリーに広げるのはなぜですか? 次の自転車は単なる別の自転車ですが、哲学的な基盤を持つ自転車はもはや別の自転車ではないため、遠くからでも自転車のように見えます!

少し余談の終わり。







restful.js



だからrestful.js。 私はそれを非常に簡単に使用しました-そして、私はそれを理解したので、数日は過ぎませんでした:







  1. all()を明示的に呼び出すたびにクールではありません。







     let games = api.all('games'); //<--   games.get(); //... games.post();
          
          





    APIリソースはフロントエンド全体を支えるものであるため、毎回手動で作成されるのはなぜですか? これらは、プロジェクトのファブリックに縫い付けられるべきものにすぎません。 api.games.get(); api.games.post()



    api.games.get(); api.games.post()



    -見た目はずっと良いです(はい、jQueryでのそのライブラリの構文の影響を表面化しただけです)。 ただし、これは回避できますが、私たちは動的なapi.games = api.all('games');



    です: api.games = api.all('games');









  2. 応答とエンティティを手動で拡張することはまったくクールではありません!







     let games = (await api.games.get()).body().data(); //<-- that sucks
          
          





    私の目は見られず、指は書かれません。 しかし、しなければなりませんでした。 ここに有用な残りのインターセプターがあります。そこに生のレスポンスをオブジェクトにデプロイする機能が実装されたばかりです。 Restful.jsにはインターセプターもありますが、ここでは控えめであり、そうではありません。







  3. ああ、また-上記のコード行はすでに2回間違っています。 まず、getではなくgetAllですが、個別のインスタンスではなくコレクションを要求しています。 第二に、data()はコレクションに対して定義されていませんUncaught (in promise) TypeError: _temp.body(...).data is not a function



    。 親切に、forEachを使用して、body()が応答から返すエンティティメソッドとして定義し、getAll()が返します。


一般的に、不便なインターフェイスの典型的な例。 これが学問的性質で有名な角度の影響なのか、それとも図書館というよりもフレームワークであることのオリエンテーションの影響なのかはわかりませんが、restful.jsが提供するインターフェースはあまり好きではありませんでした。 実際、最終的には、競合他社のインターフェイスよりもさらに恐らくそれが好きでした-明らかに、 不吉な谷の影響が影響します:理想に近いが、届きませんでしたが、愛から憎しみまではたった1つのバイクです。







私は何をしましたか?



私はrestful.jsを投げ、2つのクラスを投げました。150行のコードでは、6000のrestful.jsと基本的に同じでした(6000、 これはタイプミスではありません )。

それから、GitHubに入れて、リファクタリングして、マスターされたウェブパック(素晴らしいこと!)、Mocha + chai、sinon、travisをnpmとbowerに投稿し、ドキュメントを書き、例を書いて、最終的にこの記事を書いて、出会った人の生活を楽にしました同じ問題で。







現時点(2016年6月)では、十分なテストがなく、HEADメソッドとOPTIONSメソッドはありません。生の答えを得るのは難しく、READMEにはバッジが少なすぎます(ただ1つ、なんて恥ずかしい!..)。

ただし、これはすべて簡単に修正できます。 主なことは、another-rest-clientが提供する明確でシンプルなインターフェイスを提供することです。 私だけでなく、それを願っています。







いくつかのコード



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>'); });
      
      





投資されたリソース? 簡単に:







 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'});
      
      





async / awaitを使用すると、コードははるかに楽しくなります。







 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
      
      





ランダムな面白い事実



  1. なぜそんな名前なの? まあ、最初はただの休息クライアントでした。 しかし、この名前(および同様のいくつかの名前)はnpmで採用されており、その一意性はまあまあなので、少し自己皮肉を加えて別の休息クライアントになりました。
  2. restful.jsは、存在の最初の段階では、 another-rest-clientの最初のバージョンに非常に似ていました。 その後、どうやら彼女は企業に滑り込んだ。
  3. another-rest-clientコードにはコメントが2つしかありません(また、それらが多すぎることをamしています)が、どちらもJavascriptの方向に呪いを含んでおり、コードを完全に美しくすることはできません。
  4. WTFPLがMITライセンスとどのように異なるかはまだわかりません。


ご清聴ありがとうございました。








All Articles