SlideShare a Scribd company logo
1 of 91
JavaScript
非同期処理 入門
をド素人がお送りします
自己紹介 (1/2)
• 呼び名は?
• まっぴー (@mpyw)
• CertaiN (技術系で使ってたけど最近mpywに統一された)
• 小南響くん (@DJ_Komachi)とは何の関係ありません
• 趣味は?
• Ingress / osu! / FPS (最近全部サボってる)
• Qiitaおじさん / 知恵袋おじさん
• 学園系アニメ見てニヤニヤする
• 嫁の抱き枕ペロペロして妄想に浸る
• どこ研?何やってるの?
• (マイナーな方の) 伊藤嘉研
• ネットワーク全般
• 自分の研究はRTPプロトコル関連
自己紹介 (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ページを作るとは言ってない)
リポジトリ消滅
閉鎖
行っただけ
行っただけ
暇人
炎上しただけ
アジェンダ
1. JavaScriptの特徴
2. Callbackパターンの欠点
3. Promiseを理解する (難しいので途中まで)
4. Promiseの使い方を覚える
1. ECMAScript 6 の Promise
2. jQuery.Deferred
5. おまけ
1. ECMAScript 6 と ECMAScript 7 のこれから
1. JavaScript の特徴
JavaScriptの特徴って?
• ブラウザ上で動作する
• サーバ上でも動作する (node.js)
• Alt-JS (CoffeeScript, TypeScript) からコンパイルされて
アセンブリ言語のように使用されることが多い
• 変数宣言する際に var が必要
(付けなければグローバル変数になってしまう)
• プロトタイプベースのオブジェクト指向 (クラスが無い)
• 非同期処理がメイン
など…
非同期処理ってつまり…?
• 同期処理の場合…
「ある行の処理を開始後、完結してから次の行に移る」
• 非同期処理の場合…
「ある行の処理を開始後、直ちに次の行に移る」
func : 実行するクロージャ (関数オブジェクト)
delay : 遅延させるミリ秒時間
delayミリ秒後にfuncを実行するのを予約する
(イベントキューに入れる)
⇛ 予約自体は一瞬で終わる!
window.setTimeout(func, delay)
setTimeout の使用例
setTimeout(function () {
console.log('A');
}, 20);
console.log('B');
setTimeout(function () {
console.log('C');
}, 0);
console.log('D');
B ⇛ D ⇛ C ⇛ A
0ミリ秒の遅延
⇛ イベントキューに追加
⇛ 出来るだけ早く 実行
(すぐに実行するとは言ってない)
どの順番で表示される? 答えは…?
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. いざ実行開始!
・この行は一瞬で終わる
・リクエスト処理は
イベントキューに入る
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);
}
});
• 変数を作る必要がない!
• 見やすい!
• これで完璧だぜ!
2. Callback パターンの欠点
ところで 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);
}
});
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!');
});
3. Promise を理解する
Promise って何?
• またまたWikipediaより…
• プログラミング言語における並列処理のデザインパターン。何
らかの処理を別のスレッドで処理させる際、その処理結果の取
得を必要になるところまで後回しにする手法。処理をパイプラ
イン化させる。
※ JavaScript はシングルスレッドだが、イベントキューを使う
ことにより擬似的にマルチスレッドのようなものを実現して
いる。
Promise の理解
ぼく「ぼくJS初心者だしなぁ…絶対グダるよなぁ…」
「どうやったらまともな説明出来るかなぁ…」
ぼく「そうだ!あのサイト読み上げればいいんだ!」
↑ ご自身のスマホやタブレットで開いてください
※ 「3. プロミスは状態を持っている」までを予定
JavaScript Promise ... イカした詳細
http://p-baleine.hatenablog.com/entry/2014/03/12/190000
こ こ か ら が 本 番
• $.ajaxでも出てきたけど…
【コード】
{ A: 'foo', B: 'bar' }
【意味】
プロパティAとして 'foo'
プロパティBとして 'bar' を持つ基本オブジェクト
(JavaでいうとObjectクラスのインスタンス)
2-1. シンプルなユースケース
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
return {
then: function (callback) {
var value = 42;
callback(value);
}
};
}
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
return {
then: function (callback) {
var value = 42;
callback(value);
}
};
}
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
return {
then: function (callback) {
var value = 42;
callback(value);
}
};
}
2-1. シンプルなユースケース
doSomething().then(function(value) {
console.log('Got a value' + value);
});
function doSomething() {
return {
then: function (callback) {
var value = 42;
callback(value);
}
};
}
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を実行する
メソッド (リゾルバ)
← コンストラクタ。
外部から渡されてきた
クロージャにリゾルバを
渡している。
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);
});
こう動いて欲しい(動くとは言ってない)
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
実際はこうなってしまう!
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);
});
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);
});
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);
});
3. Promiseは状態を持っている
Pending
(待機中)
Fulfilled
Resolved
(成功した)
Rejected
(失敗した)
• Promiseの3状態
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
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);
});
成し遂げたぜ
くぅ〜疲れましたwこれにて
完結です(完結してない)
ホントだったらこの辺までやりたかった
• Promise のチェイン
• Promise のリジェクト
• Promise における例外処理
⇛ せっかくなので次章で使い方だけ紹介します!
4-1. ECMAScript 6 編
4. Promise の使い方を覚える
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と組み合わせると最強
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);
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
失敗時には 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
ファッ!?
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);
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);
実は 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);
即時に resolve / reject する
こんな関数作ったったw
var quickResolve = (value) => {
new Promise((resolve, reject) => resolve(value));
};
var quickReject = (msg) => {
new Promise((resolve, reject) => reject(msg));
};
即時に resolve / reject する
それ、最初からあるんです。
Promise.resolve = (value) => {
new Promise((resolve, reject) => resolve(value));
};
Promise.reject = (msg) => {
new Promise((resolve, reject) => reject(msg));
};
即時に 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
途中からは 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);
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]
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
4-2. jQuery編
4. Promise の使い方を覚える
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();
jQuery.ajax の返り値
• jqXHR
• Promise そのものじゃないんだけど
Promise の動きをすることが出来る
XMLHttpRequest 関連の何か
$.ajax({
type: 'GET',
url: A
}).then(function () {
return $.ajax({
type: 'GET',
url: B,
});
}).then(function () {
console.log('OK!');
});
5. おまけ
5-1. ECMAScript 6 と ECMAScript 7 のこれから
非同期処理って分かりにくい
• 初心者だけど失礼するゾ~(無知) 非同期処理分かりにく
過ギィ!自分、同期処理で書いていいっすか?めんどく
さいからやりたい放題書いてやるぜー頭悪そうなコード
書いてすみません!約束しますから!(Promiseするとは
言ってない)
Generator の出番
Generator とは
• 途中で値を返しながら処理を中断出来るクロージャ
• function *() { … } のようにアスタリスクをつけて定義
• yield キーワードで値を返す
• スライド紹介で割愛
• 引用スライド中の言語はPHP
• PHPは比較的知らない人でも読みやすい(はず)
PHPにおけるI/O多重化とyield
http://www.slideshare.net/techblogyahoo/phpioyield-phpcon2014
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));
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));
まとめ
• 馬鹿正直に書いてるとコールバックネスト地獄に陥る
• Promise を使うと多少読みにくいけど回避出来る
• jQuery では $.Deferred で以前から使えた
• ECMAScript 6 から new Promise(…) で使える
• Generator を使うと読みやすいまま回避出来る
• ECMAScript 6 から function *() { … } で使える
• co ライブラリに頼る必要がある
• async / await を使うと更にシンプルに回避できる
• ライブラリ要らず!
• 但し ECMAScript 7 からしか使えない
チカレタ…

More Related Content

What's hot

JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話disc99_
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話Kinuko Yasuda
 
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版信之 岩永
 
Boost.Spirit.QiとLLVM APIで遊ぼう
Boost.Spirit.QiとLLVM APIで遊ぼうBoost.Spirit.QiとLLVM APIで遊ぼう
Boost.Spirit.QiとLLVM APIで遊ぼうnvsofts
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26Yoshihisa Ozaki
 
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜Teppei Sato
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるKoichi Sakata
 
Groovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGGroovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGUehara Junji
 
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テストKen Morishita
 
Groovy Shell Scripting 2015
Groovy Shell Scripting 2015Groovy Shell Scripting 2015
Groovy Shell Scripting 2015Uehara Junji
 
Java EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileJava EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileNorito Agetsuma
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)信之 岩永
 
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京hecomi
 
第2回勉強会
第2回勉強会第2回勉強会
第2回勉強会Mugen Fujii
 

What's hot (19)

Mithril
MithrilMithril
Mithril
 
JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話JavaのテストGroovyでいいのではないかという話
JavaのテストGroovyでいいのではないかという話
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話
 
C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版C#/.NETがやっていること 第二版
C#/.NETがやっていること 第二版
 
Boost.Spirit.QiとLLVM APIで遊ぼう
Boost.Spirit.QiとLLVM APIで遊ぼうBoost.Spirit.QiとLLVM APIで遊ぼう
Boost.Spirit.QiとLLVM APIで遊ぼう
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26
 
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜Node.js Native ESM への道  〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
 
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみるJJUG CCC 2017 Fall オレオレJVM言語を作ってみる
JJUG CCC 2017 Fall オレオレJVM言語を作ってみる
 
最速C# 7.x
最速C# 7.x最速C# 7.x
最速C# 7.x
 
Groovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUGGroovy Bootcamp 2015 by JGGUG
Groovy Bootcamp 2015 by JGGUG
 
C#の書き方
C#の書き方C#の書き方
C#の書き方
 
最近の単体テスト
最近の単体テスト最近の単体テスト
最近の単体テスト
 
Groovy Shell Scripting 2015
Groovy Shell Scripting 2015Groovy Shell Scripting 2015
Groovy Shell Scripting 2015
 
Java EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfileJava EEを補完する仕様 MicroProfile
Java EEを補完する仕様 MicroProfile
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
 
第2回勉強会
第2回勉強会第2回勉強会
第2回勉強会
 

Similar to JavaScript 非同期処理 入門

仕事でも Groovy を使おう!
仕事でも Groovy を使おう!仕事でも Groovy を使おう!
仕事でも Groovy を使おう!Oda Shinsuke
 
Promiseでコールバック地獄から解放された話
Promiseでコールバック地獄から解放された話Promiseでコールバック地獄から解放された話
Promiseでコールバック地獄から解放された話Sota Sugiura
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライドkoturn 0;
 
20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)Yoshifumi Yamaguchi
 
F#+Erlangで簡単なシューティングゲームを作ってみている
F#+Erlangで簡単なシューティングゲームを作ってみているF#+Erlangで簡単なシューティングゲームを作ってみている
F#+Erlangで簡単なシューティングゲームを作ってみているpocketberserker
 
CoffeeScript+enchant.jsでクロージャが気持よくかけた話
CoffeeScript+enchant.jsでクロージャが気持よくかけた話CoffeeScript+enchant.jsでクロージャが気持よくかけた話
CoffeeScript+enchant.jsでクロージャが気持よくかけた話Yusuke HIDESHIMA
 
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageTaku Miyakawa
 
Javascriptで無限ループを実現する5つの方法
Javascriptで無限ループを実現する5つの方法Javascriptで無限ループを実現する5つの方法
Javascriptで無限ループを実現する5つの方法yhara
 
SwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うSwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うhayato iida
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語RShuyo Nakatani
 
ななめ45°から見たJavaOne
ななめ45°から見たJavaOneななめ45°から見たJavaOne
ななめ45°から見たJavaOneAdvancedTechNight
 
Goコンパイラのきもち
GoコンパイラのきもちGoコンパイラのきもち
Goコンパイラのきもちmjhd-devlion
 
密着!わたしのコンソールアプリ開発環境
密着!わたしのコンソールアプリ開発環境密着!わたしのコンソールアプリ開発環境
密着!わたしのコンソールアプリ開発環境Fumihito Yokoyama
 

Similar to JavaScript 非同期処理 入門 (20)

仕事でも Groovy を使おう!
仕事でも Groovy を使おう!仕事でも Groovy を使おう!
仕事でも Groovy を使おう!
 
Promiseでコールバック地獄から解放された話
Promiseでコールバック地獄から解放された話Promiseでコールバック地獄から解放された話
Promiseでコールバック地獄から解放された話
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
第2回勉強会スライド
第2回勉強会スライド第2回勉強会スライド
第2回勉強会スライド
 
20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)20130228 Goノススメ(BPStudy #66)
20130228 Goノススメ(BPStudy #66)
 
F#+Erlangで簡単なシューティングゲームを作ってみている
F#+Erlangで簡単なシューティングゲームを作ってみているF#+Erlangで簡単なシューティングゲームを作ってみている
F#+Erlangで簡単なシューティングゲームを作ってみている
 
CoffeeScript+enchant.jsでクロージャが気持よくかけた話
CoffeeScript+enchant.jsでクロージャが気持よくかけた話CoffeeScript+enchant.jsでクロージャが気持よくかけた話
CoffeeScript+enchant.jsでクロージャが気持よくかけた話
 
Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based language
 
ECMAScript没proposal追悼式
ECMAScript没proposal追悼式ECMAScript没proposal追悼式
ECMAScript没proposal追悼式
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
Javascriptで無限ループを実現する5つの方法
Javascriptで無限ループを実現する5つの方法Javascriptで無限ループを実現する5つの方法
Javascriptで無限ループを実現する5つの方法
 
SwiftでRiemann球面を扱う
SwiftでRiemann球面を扱うSwiftでRiemann球面を扱う
SwiftでRiemann球面を扱う
 
Clojure
ClojureClojure
Clojure
 
普通のプログラミング言語R
普通のプログラミング言語R普通のプログラミング言語R
普通のプログラミング言語R
 
ななめ45°から見たJavaOne
ななめ45°から見たJavaOneななめ45°から見たJavaOne
ななめ45°から見たJavaOne
 
Coqでsprintf
CoqでsprintfCoqでsprintf
Coqでsprintf
 
Introduction pp.js
Introduction pp.jsIntroduction pp.js
Introduction pp.js
 
Goコンパイラのきもち
GoコンパイラのきもちGoコンパイラのきもち
Goコンパイラのきもち
 
らくちん Go言語
らくちん Go言語らくちん Go言語
らくちん Go言語
 
密着!わたしのコンソールアプリ開発環境
密着!わたしのコンソールアプリ開発環境密着!わたしのコンソールアプリ開発環境
密着!わたしのコンソールアプリ開発環境
 

Recently uploaded

デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案sugiuralab
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)Hiroki Ichikura
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成Hiroshi Tomioka
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 

Recently uploaded (9)

デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
TataPixel: 畳の異方性を利用した切り替え可能なディスプレイの提案
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
【早稲田AI研究会 講義資料】3DスキャンとTextTo3Dのツールを知ろう!(Vol.1)
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版) 2024年4月作成
 
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 

JavaScript 非同期処理 入門

  • 2. 自己紹介 (1/2) • 呼び名は? • まっぴー (@mpyw) • CertaiN (技術系で使ってたけど最近mpywに統一された) • 小南響くん (@DJ_Komachi)とは何の関係ありません • 趣味は? • Ingress / osu! / FPS (最近全部サボってる) • Qiitaおじさん / 知恵袋おじさん • 学園系アニメ見てニヤニヤする • 嫁の抱き枕ペロペロして妄想に浸る • どこ研?何やってるの? • (マイナーな方の) 伊藤嘉研 • ネットワーク全般 • 自分の研究はRTPプロトコル関連
  • 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. アジェンダ 1. JavaScriptの特徴 2. Callbackパターンの欠点 3. Promiseを理解する (難しいので途中まで) 4. Promiseの使い方を覚える 1. ECMAScript 6 の Promise 2. jQuery.Deferred 5. おまけ 1. ECMAScript 6 と ECMAScript 7 のこれから
  • 6. JavaScriptの特徴って? • ブラウザ上で動作する • サーバ上でも動作する (node.js) • Alt-JS (CoffeeScript, TypeScript) からコンパイルされて アセンブリ言語のように使用されることが多い • 変数宣言する際に var が必要 (付けなければグローバル変数になってしまう) • プロトタイプベースのオブジェクト指向 (クラスが無い) • 非同期処理がメイン など…
  • 7. 非同期処理ってつまり…? • 同期処理の場合… 「ある行の処理を開始後、完結してから次の行に移る」 • 非同期処理の場合… 「ある行の処理を開始後、直ちに次の行に移る」 func : 実行するクロージャ (関数オブジェクト) delay : 遅延させるミリ秒時間 delayミリ秒後にfuncを実行するのを予約する (イベントキューに入れる) ⇛ 予約自体は一瞬で終わる! window.setTimeout(func, delay)
  • 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. 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. 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); } }); • 変数を作る必要がない! • 見やすい! • これで完璧だぜ!
  • 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. 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!'); });
  • 15. Promise って何? • またまたWikipediaより… • プログラミング言語における並列処理のデザインパターン。何 らかの処理を別のスレッドで処理させる際、その処理結果の取 得を必要になるところまで後回しにする手法。処理をパイプラ イン化させる。 ※ JavaScript はシングルスレッドだが、イベントキューを使う ことにより擬似的にマルチスレッドのようなものを実現して いる。
  • 17. こ こ か ら が 本 番
  • 18. • $.ajaxでも出てきたけど… 【コード】 { A: 'foo', B: 'bar' } 【意味】 プロパティAとして 'foo' プロパティBとして 'bar' を持つ基本オブジェクト (JavaでいうとObjectクラスのインスタンス) 2-1. シンプルなユースケース
  • 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. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  • 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. 2-1. シンプルなユースケース doSomething().then(function(value) { console.log('Got a value' + value); }); function doSomething() { return { then: function (callback) { var value = 42; callback(value); } }; }
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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); });
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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); });
  • 67. くぅ〜疲れましたwこれにて 完結です(完結してない) ホントだったらこの辺までやりたかった • Promise のチェイン • Promise のリジェクト • Promise における例外処理 ⇛ せっかくなので次章で使い方だけ紹介します!
  • 68. 4-1. ECMAScript 6 編 4. Promise の使い方を覚える
  • 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. 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. 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. 失敗時には 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. 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. 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. 実は 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. 即時に resolve / reject する こんな関数作ったったw var quickResolve = (value) => { new Promise((resolve, reject) => resolve(value)); }; var quickReject = (msg) => { new Promise((resolve, reject) => reject(msg)); };
  • 77. 即時に resolve / reject する それ、最初からあるんです。 Promise.resolve = (value) => { new Promise((resolve, reject) => resolve(value)); }; Promise.reject = (msg) => { new Promise((resolve, reject) => reject(msg)); };
  • 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. 途中からは 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. 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. 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. 4-2. jQuery編 4. Promise の使い方を覚える
  • 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. 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. 5. おまけ 5-1. ECMAScript 6 と ECMAScript 7 のこれから
  • 87. Generator とは • 途中で値を返しながら処理を中断出来るクロージャ • function *() { … } のようにアスタリスクをつけて定義 • yield キーワードで値を返す • スライド紹介で割愛 • 引用スライド中の言語はPHP • PHPは比較的知らない人でも読みやすい(はず) PHPにおけるI/O多重化とyield http://www.slideshare.net/techblogyahoo/phpioyield-phpcon2014
  • 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. 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. まとめ • 馬鹿正直に書いてるとコールバックネスト地獄に陥る • Promise を使うと多少読みにくいけど回避出来る • jQuery では $.Deferred で以前から使えた • ECMAScript 6 から new Promise(…) で使える • Generator を使うと読みやすいまま回避出来る • ECMAScript 6 から function *() { … } で使える • co ライブラリに頼る必要がある • async / await を使うと更にシンプルに回避できる • ライブラリ要らず! • 但し ECMAScript 7 からしか使えない