こんにちは。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です。