KMC活動ブログ

京大マイコンクラブの活動の様子を紹介します!!

ECMAScript6勉強会 第12回

こんにちは。id:tyageです。

10/13に第12回を行いました

第12回

この回では、 Promise を読みました。

Promiseは、遅延して実行される処理をうまく扱うことができるObjectです。

非同期処理などで、callback地獄と呼ばれていた問題の解決に役立ちます。

DOMのPromise実装(既にES6に移行して仕様からは消えています)や、各種ライブラリのdeferred実装を使ったことがある人は多いと思いますが、それらとはいくつか異なる部分があります。

Promiseの説明は他に詳しく解説してくれているところが多いので省略します。

内部的にはPromiseStateが"pending"の状態から始まり、"fulfilled"や"rejected"に変えることでreject, resolveが複数回呼ばれたり、resolveが呼ばれた後にthenが呼ばれた場合などの対応をしているようです。

基本形

基本形としては以下の様な感じです。

正常に処理される場合はthenで渡した1つ目の関数が呼ばれます

thenに渡す関数(onFulfilled, onRejected)を省略した場合、onFulfilledは第一引数を返すだけの関数に、onRejectedは第一引数を例外として投げる関数になるようです。

// n秒経ったらresolve
var delay = function(second) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(second)
    }, 1000 * second)
  })
}
delay(2).then(function(n) {
  // fulfilled
  console.log(n)
}, function() {
  // rejected
})

catch

thenの第2引数(onRejected)を使う代わりに、catchを利用することもできます。

エラーが投げられた場合もonRejectedが呼ばれます。

new Promise(function() {
  throw new Error(1)
}).catch(function(a) {
  console.log(a)
})
 
new Promise(function(resolve, reject) {
  reject(2)
}).catch(function(a) {
  console.log(a)
})

resolveに渡す値

無限ループするからだと思いますが、resolveにpromise自身を渡すとrejectされるようでした。

(ただし、Firefox 32だと正しく動作しない)

var p = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve(p)
  })
})
p.then(function() {
  console.log('resolved')
}, function() {
  console.log('rejected')
})

Promise.all

配列(正確にはiterableなobject)の全要素が終了したらresolveを呼ぶ

Promise.all([delay(2), delay(3)]).then(function(n) {
  console.log(n)
})

Promise.race

どれか1つでも終了したらresolveを呼ぶ

Promise.race([delay(2), delay(3)]).then(function(n) {
  console.log(n)
})

Promise.reject

渡したPromiseをrejectしたものを返します

Promise.reject(delay(2)).then(function() {
  console.log('resolved')
}, function() {
  console.log('rejected')
})

Promise.resolve

Promiseを渡した場合はそれがそのまま返ります。

それ以外の場合は、それを引数にしてresolveされます。

Promise.resolve(3).then(function(a) {
  console.log('resolved', a)
}, function(a) {
  console.log('rejected', a)
})

V8だとPromise.defer, Promise.accept, Promise.prototype.chainがまだ残っていますが、仕様にはないのでそのうち消えるだろうと思われます。

次回は10/20です。