2016-06-19

jQuery.deferredを経由しつつES2015に入ったPromiseの雰囲気を味わう

Promiseを受け取るコードの練習が狙い

今回のコードは裏では動作の確認はしてるけど全体的には雰囲気を味わうものです。Promise がなんだかよく分からないので適当に sleep して返事を返すだけのサーバをでっち上げて、これまた普段使っていないのになぜか jQuery.deferred から試してみてます。既存の道具からのステップを小さくしておくことで理解しやすくなることを狙います。

また Promise そのものや Promsie を作る部分は注目してません。あくまで Promise を利用するのはそんなに難しくないな、という雰囲気を知るためのものです。

Node.js に詳しい人は 2015年リリースの v4 から使えるので、いちいち遠回りする必要はないと思いますし、すでに動いているコードを今回のように書き換える意味はないと思います。

jQuery.deferred

jQuery.Deferred() | jQuery API Documentation

まずは jQuery.deferred で実験。

実は jQuery はかなり古い 1.5 の時代から Deferred という機能を持っていて、ajax() や getJSON() などはこの Deferred オブジェクトを返しています。そしてこの Deferred オブジェクトが Promise とよく似た動作をします。ただし fail() は jQuery 用語で、ES2015 だと catch() になります。

1) 単純な成否

$.getJSON('/api1')
  .then(function() {
     // success
  })
  .fail(function() {
    // failure
  });

これだけだと if then else のように動く。

2) エラーをまとめて拾う

$.getJSON('/api1')
  .then(function() {
    return $.getJSON('/api2');
  })
  .fail(function() {
    // failure for api1 and api2
  });

then() の中で非同期処理を実行して「Promiseを返せば」どちらで失敗しても同じ fail() を通過する。

3) 異なるPromiseのをエラーを別々に拾う

$.getJSON('/api1')
  .then(function() {
    $.getJSON('/api2')
      .then(function() {
        // success
      })
      .fail(function() {
        // failure for api2
      });
    })
  .fail(function() {
    // failure for api1
  });

非同期ではあるけど if then の入れ子のような感じで書ける。中の fail() でエラーを拾っておけば外の fail() まで伝播することはない。

Promise ( ES2015 )

今度は jQuery のように使えて jQuery より小さいけど、Deferred を持っていない UmbrellaJS を使ったうえで、Promise の部分だけ ES2015 で補います。

※ IE 対応が必要な場合はトランスパイラや Polyfill が要ります。

まずはjQuery の $.getJSON() とほぼ同じ動きをして Promise を返す wrapper 関数 u.getJSON() を定義します。1ES2015 の Promise は jQuery.deferred と違って失敗時は catch() で拾います。

※ くりかえしますが、実際のプロダクトではこんなコードは必要ないです。

Umbrella JS

wrapper

u.getJSON = function(url) {
  return new Promise(function(resolve, reject) {
    u.ajax(url,
           {method: 'GET'},
           function(err, data) {
             if ( err ) {
               reject(err);
             } else {
               resolve(data);
             }
           }
          );
  });
}

1) 単純な成否

u.getJSON('/api1')
  .then(function(data) {
    // success
  })
  .catch(function(e) {
    // failure
    console.log(e + ' : api failed.');
  });

2) エラーをまとめて拾う

u.getJSON('/api1')
  .then(function() {
    // success
    return u.getJSON('/api2');
  })
  .catch(function() {
    // failure for api1 and api2
  });

3) 異なるPromiseのエラーを別々に拾う

u.getJSON('/api1')
  .then(function() {
    u.getJSON('/api2')
      .then(function() {
        // success
      })
      .catch(function() {
        // failure for api2
      });
    })
  .catch(function() {
    // failure for api1
  });

参考

応用編

  1. ちなみに u.ajax() は特に指定しなくても JSON string だったら自動的に parse してくれる謎機能が付いてます。 

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm