superagentのjsonpプラグインをnpmで作った

何か書いてみたいけど書くことがなかったのでしばらく前に作ったsuperagentのjsonpプラグインを作った話をしてみたいと思います。

先に作ったものを貼っておきます。

www.npmjs.com

superagent

superagentはjavascriptajaxライブラリでシンプルなメソッドチェインでajaxリクエストを送ることの出来るライブラリです。

SuperAgent - Ajax with less suck

request
  .post('/api/pet')
  .send({ name: 'Manny', species: 'cat' })
  .set('X-API-Key', 'foobar')
  .set('Accept', 'application/json')
  .end(function(err, res){
    if (res.ok) {
      alert('yay got ' + JSON.stringify(res.body));
    } else {
      alert('Oh no! error ' + res.text);
    }
  });

なぜ作ったのか

superagentはajaxリクエストを送るライブラリなのでJSONPってそもそも?って感じですが、サーバに対するリクエストの書式を統一できるので(多分)多少メリットはあるのではないかなと思います。

superagentでjsonpを送ることの出来るnpmモジュールは既に別のものがありました。

www.npmjs.com

しかし、「1. エラーハンドリングが出来ない、 2. superagentのplugin機構に則っていない *1、3. ただnpmモジュールを作ってみたかった」という理由から自分で作ってみることにしました。

実装

前項でも書きましたが、superagentにはplugin機構があります。 ちなみに、これはrequest変数を関数に渡してメソッドチェイン出来るようにしてくれているだけのものです。

Request.prototype.use = function(fn) {
  fn(this);
  return this;
}

superagent-jsonpxもこのplugin機構に合うように作りました。
使い方としては以下のように使います。

var request = require('superagent');
var jsonp = require('superagent-jsonpx');
 
var options = { timeout: 3000, callbackKey: 'cb' };
 
request.get(uri)
  .use(jsonp(options))
  .end(function (err, res) {
    if (!err && res.body) {
      // request success 
      console.log(res.body);
    } else {
      // request timeout (or error) 
    }
  });

jsonp 関数に options を渡すとrequestを受け取る関数を返しています。 superagentで実際にajaxのリクエストが送られるのはendメソッドの中なのでプラグイン内でendメソッドをオーバーライドしてjsonpリクエストを送るようにしました。

ちなみにjsonpでは基本的にはエラーは取得出来ませんが、以下のページに書いてあったiframeを使う方法でエラーをハンドリングするようにしました。具体的にはiframeの特定の変数に値が一定時間経過後も入らなかった場合はエラーとして扱うようになっています。

d.hatena.ne.jp

npmモジュール周り

npmモジュールの作成に関しては以下の記事などわかりやすい記事がたくさんあったので全く困りませんでした。ありがとうございます。

qiita.com

その他、Travisやtestに使ったモジュールも初めてのものが多かったので書こうかと思いましたが大した内容でもないのに話が右往左往してしまいそうなのでこの辺で終了したいと思います。

*1:今見たらsuperagent-jsonpでもver0.0.6からplugin機構に則るようになったみたいです