SlideShare une entreprise Scribd logo
1  sur  34
Télécharger pour lire hors ligne
Promiseでコールバック地獄から解放された話
杉浦颯太(sugiuras)
はじめまして
• 杉浦 颯太(すぎうら そうた)と申します
• 2015年入社予定のクソザコ大学生です
• 現在はアルバイトとして働かせてもらっています
• 音楽好きです
• Twitter / GitHub: @sota1235
バイト初めて一ヶ月…
• 14入社の方とかに「来年上司になる方ですカァ!!!」って られる
• みんなすぐ僕より(物理的に)低い位置でお話しようとする
• あんまりいじめないでください
アジェンダ
1. コールバック地獄の話
2. Promiseの話
3. 実装例
アジェンダ
1. コールバック地獄の話
2. Promiseの話
3. 実装例
例えば
• こんなコードが書きたい
• 「hoge APIを叩いて∼」
• 「その結果を元にリクエスト作ってmoge APIを叩いて∼」
• 「さらにその結果をもとにfuga APIを叩いて∼」
• 「それをページに表示させたいヾ(ó `o)ノ」
書いてみた\(^0^)/
こうなる/(^0^)\
$.get("http://api.hoge.com?hoge=hoge", function(err, hoge) {
if(err) {
console.error(err);
return;
}
$.get(“http://api.moge.com?moge="+hoge, function(err, moge) {
if(err) {
console.error(err);
return;
}
$.get(“http://api.fuga.com?fuga="+moge, function(err, fuga) {
if(err) {
console.error(err);
return;
}
$('body').val(fuga);
});
});
});
これぞコールバック地獄
• きれいな書き方もあるかもしれないが、安直に書けばこんな感じ
• 「さらにこのAPIも噛ませて…」とかなるとどんどんネストが…
• 「あ、この処理をパラメータ変えて3回飛ばして」とか上司に言
われたらもう…
• 読むのも書くのもつらいですよね
そこでPromise
Promiseとはなんぞやと、この地獄の抜け出し方を見てみましょう
アジェンダ
1. コールバック地獄の話
2. Promiseの話
3. 実装例
Promise is 何
• 非同期処理の結果を抱え込むオブジェクト
• 処理の結果に影響されることなく値を返す約束手形を渡してくれる
のがPromiseオブジェクト
• この約束手形をつないだりすることでネストが深くなるのが防げ
る
• また、処理の順序等の制御が簡単になる
なるほどわからん(́・ω・`)
インスタンス生成
• new Promise(); ←こんだけ!
• 基本的な使い方は
1. 関数を作る
2. Promiseインスタンスを生成する
3. インスタンスの引数に処理を書き、約束を取り付ける
Promise化された関数
/* not Promise */
var func = function(num, callback) {
if(num % 2 == 0) {
callback(null, num / 2);
} else {
callback("Error", null);
}
}
!
/* Promise */
var pfunc = function(num) {
var promise = new Promise(function(resolve, reject) {
if(num % 2 == 0) {
resolve(num / 2); // success
} else {
reject(“Error"); // failure
}
});
return promise;
}
Promise化された関数を使う
/* not Promise */
func(4, function(err, result) {
if(err) {
console.error(err);
return;
}
console.log(result);
});
!
/* Promise */
pfunc.then(function(result) {
console.log(result); // success
}).catch(function(err) {
console.error(err); // failure
});
.then()
• resolve()された結果を受け取るメソッド
! var p = new Promise(function(resolve, reject) { resolve("Hello, World!"); });
!
p.then(function(result) {
console.log(result); // Hello, World!
});
.catch()
• reject()された結果を受け取るメソッド
• いわゆるエラー処理
!
!
var p = new Promise(function(resolve, reject) { reject(“ERROR!!”); });
!
p.catch(function(err) {
console.error(err); // ERROR!!
});
.all()
• Promiseオブジェクトが持つメソッド
• 引数にPromiseインスタンスの配列を渡す
• 全てのインスタンスの処理が終わった時、配列の順番に結果が格納
された配列が帰ってくる
!
!
.all()
var p1 = new Promise(function(resolve, reject) { resolve(“1”); });
var p2 = new Promise(function(resolve, reject) { resolve(“2”); });
var promises = [p1, p2];
Promise.all(promises).then(function(results) {
console.log(results); // [1, 2]
});
.race()
• Promiseオブジェクトが持つメソッド
• 引数にPromiseインスタンスの配列を渡す
• 全てのインスタンスのどれか1つでも処理が終わるとその結果だけ
を返す
• 1つの処理が終わった時点で他の処理が破棄されるわけではないの
で注意
!
var p1 = new Promise(function(resolve, reject) { resolve("1"); });
var p2 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("2");
}, 1000);
});
var promises = [p1, p2];
Promise.race(promises).then(function(result) {
console.log(result); // 1
});
.race()
結局Promiseの何が嬉しいの
• ネストが浅くなる
• 非同期処理の制御が容易になる
• メソッドチェーンで読みやすく
• 非同期関数のエラー処理の仕様が強制的に統一される
• reject()でエラー処理を行うため
• 全てはcatch()に吸収される
注意すべきとこ
• テストをするのに工夫が必要(らしい)
• サポートしてないブラウザがある
• → polyfillライブラリを使用することで解決できる
• es6-promiseというのが一番よさげ
アジェンダ
1. コールバック地獄の話
2. Promiseの話
3. 実装例
さっきのコールバック地獄
$.get("http://api.hoge.com?hoge=hoge", function(err, hoge) {
if(err) {
console.error(err);
return;
}
$.get(“http://api.moge.com?moge="+hoge, function(err, moge) {
if(err) {
console.error(err);
return;
}
$.get(“http://api.fuga.com?fuga="+moge, function(err, fuga) {
if(err) {
console.error(err);
return;
}
$('body').val(fuga);
});
});
});
関数化 & Promise化
• 先ほどの3つのAPIを叩く処理を別々に関数化する
• かつPromise化する
関数化 & Promise化(hoge API)
var hoge = function() {
return new Promise(function(resolve, reject) {
$.get("http://api.hoge.com?hoge=hoge", function(err, hoge) {
if(err) reject(err);
resolve(hoge);
});
});
}
関数化 & Promise化(moge/fuga API)
var moge = function(hoge) {
return new Promise(function(resolve, reject) {
$.get("http://api.moge.com?moge"+hoge, function(err, moge) {
if(err) reject(err);
resolve(moge);
});
});
}
var fuga = function(moge) {
return new Promise(function(resolve, reject) {
$.get("http://api.fuga.com?fuga"+moge, function(err, fuga) {
if(err) reject(err);
resolve(fuga);
});
});
}
つなげる!!!!
hoge.then(moge)
.then(fuga)
.then(function(result) {
$('body').val(result);
})
.catch(function(err) {
console.error(err);
});
つなげる!(補足)
hoge
.then(moge)
/*
* hoge.then(function(result) { moge(result) }) と同じ
*/
浅くなったー(*́ω`*)
• then()とcatch()をつなげて処理を渡していくのでネストが深くな
らない
• Promiseオブジェクト以外の処理も渡すことができる
• Promiseでなくても明示的にreturnすることでまたthen()をつな
げることができる
参考
• Promiseの本
• http://azu.github.io/promises-book/
ご静聴ありがとうございました

Contenu connexe

Similaire à Promiseでコールバック地獄から解放された話

Closures and methodMissing are real
Closures and methodMissing are realClosures and methodMissing are real
Closures and methodMissing are real
Takahiro Sugiura
 
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミング
lestrrat
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
 

Similaire à Promiseでコールバック地獄から解放された話 (10)

Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
英語コーダー大阪 ー 初めての英語コーダー教室
英語コーダー大阪 ー 初めての英語コーダー教室英語コーダー大阪 ー 初めての英語コーダー教室
英語コーダー大阪 ー 初めての英語コーダー教室
 
Closures and methodMissing are real
Closures and methodMissing are realClosures and methodMissing are real
Closures and methodMissing are real
 
No skk, no life.
No skk, no life.No skk, no life.
No skk, no life.
 
仕事でも Groovy を使おう!
仕事でも Groovy を使おう!仕事でも Groovy を使おう!
仕事でも Groovy を使おう!
 
Perl 非同期プログラミング
Perl 非同期プログラミングPerl 非同期プログラミング
Perl 非同期プログラミング
 
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テスト
 
Programming camp 2010 debug hacks
Programming camp 2010 debug hacksProgramming camp 2010 debug hacks
Programming camp 2010 debug hacks
 
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 RubyをコンパイルしようCookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 

Plus de Sota Sugiura (9)

「データベース実践入門」から学ぶリレーショナルモデル
「データベース実践入門」から学ぶリレーショナルモデル「データベース実践入門」から学ぶリレーショナルモデル
「データベース実践入門」から学ぶリレーショナルモデル
 
TechCrunchTokyo Hackathon 2015
TechCrunchTokyo Hackathon 2015TechCrunchTokyo Hackathon 2015
TechCrunchTokyo Hackathon 2015
 
コミットメッセージの話
コミットメッセージの話コミットメッセージの話
コミットメッセージの話
 
HTTP2入門
HTTP2入門HTTP2入門
HTTP2入門
 
HTTP入門
HTTP入門HTTP入門
HTTP入門
 
今さら聞けないXSS
今さら聞けないXSS今さら聞けないXSS
今さら聞けないXSS
 
各ブラウザでの均等割り付け比較
各ブラウザでの均等割り付け比較各ブラウザでの均等割り付け比較
各ブラウザでの均等割り付け比較
 
GitHubにおける開発フローについてのお話
GitHubにおける開発フローについてのお話GitHubにおける開発フローについてのお話
GitHubにおける開発フローについてのお話
 
Web Audio API 入門
Web Audio API 入門Web Audio API 入門
Web Audio API 入門
 

Promiseでコールバック地獄から解放された話