Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
JavaScript
非同期処理 入門
をド素人がお送りします
自己紹介 (1/2)
• 呼び名は?
• まっぴー (@mpyw)
• CertaiN (技術系で使ってたけど最近mpywに統一された)
• 小南響くん (@DJ_Komachi)とは何の関係ありません
• 趣味は?
• Ingress / o...
自己紹介 (2/2)
• 今までの実績は?
• PHP製TwitterAPIライブラリ – UltimateOAuth
• PHP製TwitterAPIライブラリ(改良版) – TwistOAuth
• JavaScript製Chrome用Tw...
アジェンダ
1. JavaScriptの特徴
2. Callbackパターンの欠点
3. Promiseを理解する (難しいので途中まで)
4. Promiseの使い方を覚える
1. ECMAScript 6 の Promise
2. jQue...
1. JavaScript の特徴
JavaScriptの特徴って?
• ブラウザ上で動作する
• サーバ上でも動作する (node.js)
• Alt-JS (CoffeeScript, TypeScript) からコンパイルされて
アセンブリ言語のように使用されることが多い
...
非同期処理ってつまり…?
• 同期処理の場合…
「ある行の処理を開始後、完結してから次の行に移る」
• 非同期処理の場合…
「ある行の処理を開始後、直ちに次の行に移る」
func : 実行するクロージャ (関数オブジェクト)
delay : 遅...
setTimeout の使用例
setTimeout(function () {
console.log('A');
}, 20);
console.log('B');
setTimeout(function () {
console.log(...
XMLHttpRequest の使用例
• XMLHttpRequest って何?
• 非同期で通信するためのオブジェクト
(ここではより簡便なLEVEL2を扱います)
var xhr = new XMLHttpRequest();
xhr.o...
jQuery.ajax の使用例
• jQuery って何?
• 標準のJavaScriptをより便利にするライブラリ
• 「jQuery」は「$」とも書ける
• jQuery.ajax って何?
• XMLHttpRequestを簡便に書くた...
2. Callback パターンの欠点
ところで Callback って何?
• Wikipedia より…
• コールバック(英: Callback)とは、プログラミングにおい
て、他のコードの引数として渡されるサブルーチンである。
これにより、低レベルの抽象化層が高レベルの層で定...
Callback のネスト
• 例: もしAへのリクエストが成功したら、
続けてBへのリクエストも実行する。
更にBへのリクエストが成功したら、
「OK!」 とログに出す。
$.ajax({
type: 'GET',
url: A,
succe...
3. Promise を理解する
Promise って何?
• またまたWikipediaより…
• プログラミング言語における並列処理のデザインパターン。何
らかの処理を別のスレッドで処理させる際、その処理結果の取
得を必要になるところまで後回しにする手法。処理をパイプラ
イ...
Promise の理解
ぼく「ぼくJS初心者だしなぁ…絶対グダるよなぁ…」
「どうやったらまともな説明出来るかなぁ…」
ぼく「そうだ!あのサイト読み上げればいいんだ!」
↑ ご自身のスマホやタブレットで開いてください
※ 「3. プロミスは状態...
こ こ か ら が 本 番
• $.ajaxでも出てきたけど…
【コード】
{ A: 'foo', B: 'bar' }
【意味】
プロパティAとして 'foo'
プロパティBとして 'bar' を持つ基本オブジェクト
(JavaでいうとObjectクラスのインスタンス)...
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
ret...
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
ret...
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
ret...
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
ret...
2-1-1. プロミス型を定義する
オレオレクラス構文を勝手に導入して書き直すと…
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
functi...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = …;
function then(cb) {
callback = cb;
}
function resolve(value) {
callbac...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
2-1-1. プロミス型を定義する
class Promise {
var callback = null;
function then(cb) {
callback = cb;
}
function resolve(value) {
call...
3. Promiseは状態を持っている
Pending
(待機中)
Fulfilled
Resolved
(成功した)
Rejected
(失敗した)
• Promiseの3状態
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred;
function resolve(newValue) {
valu...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred;
function resolve(newValue) {
value = ne...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred = …;
function resolve(newValue) {
value ...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred = …;
function resolve(newValue) {
value ...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred = …;
function resolve(newValue) {
value ...
3.Promiseは状態を持っている
class Promise {
var state = 'pending';
var value;
var deferred = …;
function resolve(newValue) {
value ...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
3.Promiseは状態を持っている
class Promise {
var state = 'resolved';
var value = 42;
var deferred = …;
function resolve(newValue) {
...
成し遂げたぜ
くぅ〜疲れましたwこれにて
完結です(完結してない)
ホントだったらこの辺までやりたかった
• Promise のチェイン
• Promise のリジェクト
• Promise における例外処理
⇛ せっかくなので次章で使い方だけ紹介します!
4-1. ECMAScript 6 編
4. Promise の使い方を覚える
ECMAScript 6
• ECMAScript ってそもそも何?
• JavaScript の標準規格
• ネットワークで例えると
• TCP/IP ⇛ JavaScript
• OSI参照モデル ⇛ ECMAScript
• 現在最も普及...
then のチェイン
ArrowFunctionを使いながら復習
var foo = (i) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.l...
then のチェイン
then から呼ばれるコールバックの中で
Promise をreturn
⇛ then がチェイン出来る!
var foo = (i) => {
return new Promise((resolve, reject) =...
失敗時には reject を利用
then の第2引数コールバックは reject 時に発火
⇛ 以降の resolve は行われない
var foo = (i) => {
return new Promise((resolve, reject...
reject は末尾だけで十分
末尾で必ず拾ってくれます
var foo = (i) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (i < 3) {
...
reject のみの then は catch に
こんな書き方もできます
var foo = (i) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (...
実は throw も捕まえられる?
※ 但し非同期処理では不可能
var foo = (i) => {
return new Promise((resolve, reject) => {
if (Math.random() < 0.5) {
c...
即時に resolve / reject する
こんな関数作ったったw
var quickResolve = (value) => {
new Promise((resolve, reject) => resolve(value));
};
v...
即時に resolve / reject する
それ、最初からあるんです。
Promise.resolve = (value) => {
new Promise((resolve, reject) => resolve(value));
};
...
即時に resolve / reject する
無理矢理つかってみよう
var a = (i) => Promise.resolve(i + 1);
var b = (i) => Promise.resolve(i + 1);
var c = ...
途中からは return = resolve
実はこう書いても自動的に Promise.resolve してくれる
var a = (i) => Promise.resolve(i + 1);
var b = (i) => i + 1;
var...
Promise で並列処理 (all)
• 同時にスタートして全部の成功を期待する
var waitSec = (i) => {
console.log('I wait for ' + i + ' sec');
return new Promi...
Promise で並列処理 (race)
• 同時にスタートして一番早い成功または失敗を受け付ける
⇛ 一番早い「成功のみ」ってどうやって書くの?
⇛ 「Promise.any」でググるとライブラリとかあるよ
var waitSec = (i)...
4-2. jQuery編
4. Promise の使い方を覚える
jQuery にも Promise はある!
• その前に ECMAScript6 の Promise の別の書き方を紹介
• jQuery
return new Promise((resolve, reject) => {
if (…) {
...
jQuery.ajax の返り値
• jqXHR
• Promise そのものじゃないんだけど
Promise の動きをすることが出来る
XMLHttpRequest 関連の何か
$.ajax({
type: 'GET',
url: A
})....
5. おまけ
5-1. ECMAScript 6 と ECMAScript 7 のこれから
非同期処理って分かりにくい
• 初心者だけど失礼するゾ~(無知) 非同期処理分かりにく
過ギィ!自分、同期処理で書いていいっすか?めんどく
さいからやりたい放題書いてやるぜー頭悪そうなコード
書いてすみません!約束しますから!(Promiseす...
Generator とは
• 途中で値を返しながら処理を中断出来るクロージャ
• function *() { … } のようにアスタリスクをつけて定義
• yield キーワードで値を返す
• スライド紹介で割愛
• 引用スライド中の言語はP...
Generator を活用
var foo = (i) => {
return Promise.resolve(i).then((i) => {
return i + 1;
}).then((i) => {
return i + 1;
}).t...
ECMAScript 7 だと…
var co = require('co');
var gen = function *(i) {
i = yield i + 1;
i = yield i + 1;
i = yield i + 1;
yiel...
まとめ
• 馬鹿正直に書いてるとコールバックネスト地獄に陥る
• Promise を使うと多少読みにくいけど回避出来る
• jQuery では $.Deferred で以前から使えた
• ECMAScript 6 から new Promise(...
チカレタ…
Upcoming SlideShare
Loading in …5
×

JavaScript 非同期処理 入門

身内LT用

  • Login to see the comments

JavaScript 非同期処理 入門

  1. 1. JavaScript 非同期処理 入門 をド素人がお送りします
  2. 2. 自己紹介 (1/2) • 呼び名は? • まっぴー (@mpyw) • CertaiN (技術系で使ってたけど最近mpywに統一された) • 小南響くん (@DJ_Komachi)とは何の関係ありません • 趣味は? • Ingress / osu! / FPS (最近全部サボってる) • Qiitaおじさん / 知恵袋おじさん • 学園系アニメ見てニヤニヤする • 嫁の抱き枕ペロペロして妄想に浸る • どこ研?何やってるの? • (マイナーな方の) 伊藤嘉研 • ネットワーク全般 • 自分の研究はRTPプロトコル関連
  3. 3. 自己紹介 (2/2) • 今までの実績は? • PHP製TwitterAPIライブラリ – UltimateOAuth • PHP製TwitterAPIライブラリ(改良版) – TwistOAuth • JavaScript製Chrome用Twitter公式Web 正規表現ミュートプラグイン – TwitterCustomizedMuting • PHP製ガラケー向けTwitterWebアプリ – GalaTwi • seccamp 2014 web • pixiv summer internship 2014 engineer • 知恵袋回答数4500件 BA率73% • Qiita 6000 Contribution • JavaScriptできるの? • できません • PHPは好きです(Webページを作るとは言ってない) リポジトリ消滅 閉鎖 行っただけ 行っただけ 暇人 炎上しただけ
  4. 4. アジェンダ 1. JavaScriptの特徴 2. Callbackパターンの欠点 3. Promiseを理解する (難しいので途中まで) 4. Promiseの使い方を覚える 1. ECMAScript 6 の Promise 2. jQuery.Deferred 5. おまけ 1. ECMAScript 6 と ECMAScript 7 のこれから
  5. 5. 1. JavaScript の特徴
  6. 6. JavaScriptの特徴って? • ブラウザ上で動作する • サーバ上でも動作する (node.js) • Alt-JS (CoffeeScript, TypeScript) からコンパイルされて アセンブリ言語のように使用されることが多い • 変数宣言する際に var が必要 (付けなければグローバル変数になってしまう) • プロトタイプベースのオブジェクト指向 (クラスが無い) • 非同期処理がメイン など…
  7. 7. 非同期処理ってつまり…? • 同期処理の場合… 「ある行の処理を開始後、完結してから次の行に移る」 • 非同期処理の場合… 「ある行の処理を開始後、直ちに次の行に移る」 func : 実行するクロージャ (関数オブジェクト) delay : 遅延させるミリ秒時間 delayミリ秒後にfuncを実行するのを予約する (イベントキューに入れる) ⇛ 予約自体は一瞬で終わる! window.setTimeout(func, delay)
  8. 8. setTimeout の使用例 setTimeout(function () { console.log('A'); }, 20); console.log('B'); setTimeout(function () { console.log('C'); }, 0); console.log('D'); B ⇛ D ⇛ C ⇛ A 0ミリ秒の遅延 ⇛ イベントキューに追加 ⇛ 出来るだけ早く 実行 (すぐに実行するとは言ってない) どの順番で表示される? 答えは…?
  9. 9. XMLHttpRequest の使用例 • XMLHttpRequest って何? • 非同期で通信するためのオブジェクト (ここではより簡便なLEVEL2を扱います) var xhr = new XMLHttpRequest(); xhr.open('GET', '/contents.html'); xhr.onload = function () { console.log(xhr.response); }; xhr.onerror = function () { console.error(xhr.response); }; xhr.send(null); 1. インスタンス生成 2. /contents.htmlにGETで アクセスすることを設定 3. 正常完了時のイベントを設定 4. エラー時のイベントを設定 5. いざ実行開始! ・この行は一瞬で終わる ・リクエスト処理は イベントキューに入る
  10. 10. jQuery.ajax の使用例 • jQuery って何? • 標準のJavaScriptをより便利にするライブラリ • 「jQuery」は「$」とも書ける • jQuery.ajax って何? • XMLHttpRequestを簡便に書くためのメソッド $.ajax({ type: 'GET', url: '/contents.html', success: function (data) { console.log(data); }, error: function (xhr) { console.error(xhr.response); } }); • 変数を作る必要がない! • 見やすい! • これで完璧だぜ!
  11. 11. 2. Callback パターンの欠点
  12. 12. ところで Callback って何? • Wikipedia より… • コールバック(英: Callback)とは、プログラミングにおい て、他のコードの引数として渡されるサブルーチンである。 これにより、低レベルの抽象化層が高レベルの層で定義さ れたサブルーチン(または関数)を呼び出せるようになる。 • つまりJavaScriptだと? var xhr = new XMLHttpRequest(); xhr.open('GET', '/contents.html'); xhr.onload = function () { console.log(xhr.response); }; xhr.onerror = function () { console.error(xhr.response); }; xhr.send(null); $.ajax({ type: 'GET', url: '/contents.html', success: function (data) { console.log(data); }, error: function (xhr) { console.error(xhr.response); } }); var xhr = new XMLHttpRequest(); xhr.open('GET', '/contents.html'); xhr.onload = function () { console.log(xhr.response); }; xhr.onerror = function () { console.error(xhr.response); }; xhr.send(null); $.ajax({ type: 'GET', url: '/contents.html', success: function (data) { console.log(data); }, error: function (xhr) { console.error(xhr.response); } });
  13. 13. Callback のネスト • 例: もしAへのリクエストが成功したら、 続けてBへのリクエストも実行する。 更にBへのリクエストが成功したら、 「OK!」 とログに出す。 $.ajax({ type: 'GET', url: A, success: function () { $.ajax({ type: 'GET', url: B, success: function () { console.log('OK!'); } }); } }); 新しい 書き方 $.ajax({ type: 'GET', url: A }).then(function () { return $.ajax({ type: 'GET', url: B, }); }).then(function () { console.log('OK!'); });
  14. 14. 3. Promise を理解する
  15. 15. Promise って何? • またまたWikipediaより… • プログラミング言語における並列処理のデザインパターン。何 らかの処理を別のスレッドで処理させる際、その処理結果の取 得を必要になるところまで後回しにする手法。処理をパイプラ イン化させる。 ※ JavaScript はシングルスレッドだが、イベントキューを使う ことにより擬似的にマルチスレッドのようなものを実現して いる。
  16. 16. Promise の理解 ぼく「ぼくJS初心者だしなぁ…絶対グダるよなぁ…」 「どうやったらまともな説明出来るかなぁ…」 ぼく「そうだ!あのサイト読み上げればいいんだ!」 ↑ ご自身のスマホやタブレットで開いてください ※ 「3. プロミスは状態を持っている」までを予定 JavaScript Promise ... イカした詳細 http://p-baleine.hatenablog.com/entry/2014/03/12/190000
  17. 17. こ こ か ら が 本 番
  18. 18. • $.ajaxでも出てきたけど… 【コード】 { A: 'foo', B: 'bar' } 【意味】 プロパティAとして 'foo' プロパティBとして 'bar' を持つ基本オブジェクト (JavaでいうとObjectクラスのインスタンス) 2-1. シンプルなユースケース
  19. 19. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  20. 20. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  21. 21. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  22. 22. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  23. 23. 2-1-1. プロミス型を定義する オレオレクラス構文を勝手に導入して書き直すと… class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } ← Callbackを格納するプロパティ ← Callbackを予約するメソッド ← 予約されたCallbackを実行する メソッド (リゾルバ) ← コンストラクタ。 外部から渡されてきた クロージャにリゾルバを 渡している。
  24. 24. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); }); こう動いて欲しい(動くとは言ってない)
  25. 25. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  26. 26. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  27. 27. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  28. 28. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  29. 29. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  30. 30. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  31. 31. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  32. 32. 2-1-1. プロミス型を定義する class Promise { var callback = …; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  33. 33. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); }); 実際はこうなってしまう!
  34. 34. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  35. 35. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  36. 36. 2-1-1. プロミス型を定義する class Promise { var callback = null; function then(cb) { callback = cb; } function resolve(value) { callback(value); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } doSomething().then(function(value) { console.log('Got a value:' + value); });
  37. 37. 3. Promiseは状態を持っている Pending (待機中) Fulfilled Resolved (成功した) Rejected (失敗した) • Promiseの3状態
  38. 38. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  39. 39. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  40. 40. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  41. 41. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  42. 42. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  43. 43. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  44. 44. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  45. 45. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  46. 46. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  47. 47. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  48. 48. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  49. 49. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  50. 50. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { var value = 42; resolve(value); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); promise.then(function(value) { console.log('Got a value:' + value); });
  51. 51. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  52. 52. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  53. 53. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  54. 54. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  55. 55. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  56. 56. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  57. 57. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  58. 58. 3.Promiseは状態を持っている class Promise { var state = 'pending'; var value; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  59. 59. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  60. 60. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  61. 61. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  62. 62. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  63. 63. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  64. 64. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  65. 65. 3.Promiseは状態を持っている class Promise { var state = 'resolved'; var value = 42; var deferred = …; function resolve(newValue) { value = newValue; state = 'resolved'; if (deferred) { handle(deferred); } } function handle(onResolved) { if (state === 'pending') { deferred = onResolved; return; } onResolved(value); } function then(onResolved) { handle(onResolved); } function Promise(fn) { fn(resolve); } } function doSomething() { return new Promise(function(resolve) { setTimeout(function () { var value = 42; resolve(value); }, 114514); }); } var promise = doSomething(); promise.then(function(value) { console.log('Got a value:' + value); }); sleep(114514); promise.then(function(value) { console.log('Got a value:' + value); });
  66. 66. 成し遂げたぜ
  67. 67. くぅ〜疲れましたwこれにて 完結です(完結してない) ホントだったらこの辺までやりたかった • Promise のチェイン • Promise のリジェクト • Promise における例外処理 ⇛ せっかくなので次章で使い方だけ紹介します!
  68. 68. 4-1. ECMAScript 6 編 4. Promise の使い方を覚える
  69. 69. ECMAScript 6 • ECMAScript ってそもそも何? • JavaScript の標準規格 • ネットワークで例えると • TCP/IP ⇛ JavaScript • OSI参照モデル ⇛ ECMAScript • 現在最も普及しているのは ECMAScript 5 互換の実装 (多分) • ECMAScript 6 の新機能 (ごく一部) • Arrow Function … function (a) { return b; } を (a) => { return b; } または (a) => b と書ける this がより直感的に使えるメリットもある • Class … 「オレオレクラス構文」みたいなのがマジで書ける 但しメンバ変数は含められない… • Promise … 今回途中まで実装したようなやつ • Generator … 途中で中断してまだ再開したり出来る関数 Promiseと組み合わせると最強
  70. 70. then のチェイン ArrowFunctionを使いながら復習 var foo = (i) => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('OK: ' + i); resolve(i + 1); }, 1000); }); }; foo(1).then(foo).then(foo).then(foo);
  71. 71. then のチェイン then から呼ばれるコールバックの中で Promise をreturn ⇛ then がチェイン出来る! var foo = (i) => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('OK: ' + i); resolve(i + 1); }, 1000); }); }; foo(1).then(foo).then(foo).then(foo); OK: 1 OK: 2 OK: 3 OK: 4
  72. 72. 失敗時には reject を利用 then の第2引数コールバックは reject 時に発火 ⇛ 以降の resolve は行われない var foo = (i) => { return new Promise((resolve, reject) => { setTimeout(() => { if (i < 3) { console.log('OK: ' + i); resolve(i + 1); } else { reject('ファッ!?'); } }, 1000); }); }; var bar = (msg) => { console.error(msg); }; foo(1).then(foo, bar).then(foo, bar).then(foo, bar); OK: 1 OK: 2 ファッ!?
  73. 73. reject は末尾だけで十分 末尾で必ず拾ってくれます var foo = (i) => { return new Promise((resolve, reject) => { setTimeout(() => { if (i < 3) { console.log('OK: ' + i); resolve(i + 1); } else { reject('ファッ!?'); } }, 1000); }); }; var bar = (msg) => { console.error(msg); }; foo(1).then(foo).then(foo).then(foo).then(null, bar);
  74. 74. reject のみの then は catch に こんな書き方もできます var foo = (i) => { return new Promise((resolve, reject) => { setTimeout(() => { if (i < 3) { console.log('OK: ' + i); resolve(i + 1); } else { reject('ファッ!?'); } }, 1000); }); }; var bar = (msg) => { console.error(msg); }; foo(1).then(foo).then(foo).then(foo).catch(bar);
  75. 75. 実は throw も捕まえられる? ※ 但し非同期処理では不可能 var foo = (i) => { return new Promise((resolve, reject) => { if (Math.random() < 0.5) { console.log('OK'); resolve(); } else { throw new Error('ファッ!?'); } }); }; var bar = (e) => { console.error(e.message); }; foo(1).catch(bar);
  76. 76. 即時に resolve / reject する こんな関数作ったったw var quickResolve = (value) => { new Promise((resolve, reject) => resolve(value)); }; var quickReject = (msg) => { new Promise((resolve, reject) => reject(msg)); };
  77. 77. 即時に resolve / reject する それ、最初からあるんです。 Promise.resolve = (value) => { new Promise((resolve, reject) => resolve(value)); }; Promise.reject = (msg) => { new Promise((resolve, reject) => reject(msg)); };
  78. 78. 即時に resolve / reject する 無理矢理つかってみよう var a = (i) => Promise.resolve(i + 1); var b = (i) => Promise.resolve(i + 1); var c = (i) => Promise.resolve(i + 1); var d = (i) => console.log(i); a(10).then(b).then(c).then(d); 13
  79. 79. 途中からは return = resolve 実はこう書いても自動的に Promise.resolve してくれる var a = (i) => Promise.resolve(i + 1); var b = (i) => i + 1; var c = (i) => i + 1; var d = (i) => console.log(i); a(10).then(b).then(c).then(d);
  80. 80. Promise で並列処理 (all) • 同時にスタートして全部の成功を期待する var waitSec = (i) => { console.log('I wait for ' + i + ' sec'); return new Promise((resolve, reject) => { setTimeout(() => resolve(i), i * 1000); }); }; var promises = [waitSec(1), waitSec(2), waitSec(3)]; Promise.all(promises) .then(results => console.log(results)); I wait for 1 sec I wait for 2 sec I wait for 3 sec [1, 2, 3]
  81. 81. Promise で並列処理 (race) • 同時にスタートして一番早い成功または失敗を受け付ける ⇛ 一番早い「成功のみ」ってどうやって書くの? ⇛ 「Promise.any」でググるとライブラリとかあるよ var waitSec = (i) => { console.log('I wait for ' + i + ' sec'); return new Promise((resolve, reject) => { setTimeout(() => resolve(i), i * 1000); }); }; var promises = [waitSec(1), waitSec(2), waitSec(3)]; Promise.race(promises) .then(result => console.log(result)); I wait for 1 sec I wait for 2 sec I wait for 3 sec 1
  82. 82. 4-2. jQuery編 4. Promise の使い方を覚える
  83. 83. jQuery にも Promise はある! • その前に ECMAScript6 の Promise の別の書き方を紹介 • jQuery return new Promise((resolve, reject) => { if (…) { resolve(…); } else { reject(…); } }); var deferred = Promise.defer(); if (…) { deferred.resolve(…); } else { deferred.reject(…); } return deferred.promise; ・ネストが減る! ・でも非標準/非推奨 var deferred = $.Deferred(); if (…) { deferred.resolve(…); } else { deferred.reject(…); } return deferred.promise();
  84. 84. jQuery.ajax の返り値 • jqXHR • Promise そのものじゃないんだけど Promise の動きをすることが出来る XMLHttpRequest 関連の何か $.ajax({ type: 'GET', url: A }).then(function () { return $.ajax({ type: 'GET', url: B, }); }).then(function () { console.log('OK!'); });
  85. 85. 5. おまけ 5-1. ECMAScript 6 と ECMAScript 7 のこれから
  86. 86. 非同期処理って分かりにくい • 初心者だけど失礼するゾ~(無知) 非同期処理分かりにく 過ギィ!自分、同期処理で書いていいっすか?めんどく さいからやりたい放題書いてやるぜー頭悪そうなコード 書いてすみません!約束しますから!(Promiseするとは 言ってない) Generator の出番
  87. 87. Generator とは • 途中で値を返しながら処理を中断出来るクロージャ • function *() { … } のようにアスタリスクをつけて定義 • yield キーワードで値を返す • スライド紹介で割愛 • 引用スライド中の言語はPHP • PHPは比較的知らない人でも読みやすい(はず) PHPにおけるI/O多重化とyield http://www.slideshare.net/techblogyahoo/phpioyield-phpcon2014
  88. 88. Generator を活用 var foo = (i) => { return Promise.resolve(i).then((i) => { return i + 1; }).then((i) => { return i + 1; }).then((i) => { return i + 1; }).then((i) => { return i + 1; }) }; foo(1).then((i) => console.log(i)); var co = require('co'); var gen = function *(i) { i = yield i + 1; i = yield i + 1; i = yield i + 1; yield i + 1; }; co(gen(1)).then(i => console.log(i));
  89. 89. ECMAScript 7 だと… var co = require('co'); var gen = function *(i) { i = yield i + 1; i = yield i + 1; i = yield i + 1; yield i + 1; }; co(gen(1)).then(i => console.log(i)); • async / await という C# のような構文が使える • その代わりクロージャは使えない async function foo(i) { i = await i + 1; i = await i + 1; i = await i + 1; return await i + 1; }; foo(1).then(i => console.log(i));
  90. 90. まとめ • 馬鹿正直に書いてるとコールバックネスト地獄に陥る • Promise を使うと多少読みにくいけど回避出来る • jQuery では $.Deferred で以前から使えた • ECMAScript 6 から new Promise(…) で使える • Generator を使うと読みやすいまま回避出来る • ECMAScript 6 から function *() { … } で使える • co ライブラリに頼る必要がある • async / await を使うと更にシンプルに回避できる • ライブラリ要らず! • 但し ECMAScript 7 からしか使えない
  91. 91. チカレタ…

×