-
Notifications
You must be signed in to change notification settings - Fork 0
DNET_PromiseJavaScript
- 戻る
-
JavaScriptのスレッド処理
- Promise (JavaScript)(本ページ)
- async/await (JavaScript)
-
JavaScriptのスレッド処理
構造化コールバック
-
Promiseではコールバックを関数に渡すかわりに、
コールバックを付属させたPromiseオブジェクトをリターンする。 -
これにより、
- インターフェイス、処理の書き方を統一することができ、
- 実行と完了に遅延がある処理をうまい具合に扱うことができる。
-
この動作は「デザイン・パターン」から以下のように説明できる。
「非同期関数は呼び出し元の関数に呼ばれた証を事前に返しておく。
結果は、非同期処理が終了し次第、その証を持っている関数に通知する。」 -
.NETのTaskに近いと言えば近いらしい(厳密には違うが)。
- 参考:[C#]TaskクラスをJavaScriptのPromiseっぽく使ってみる実験 - Qiita
https://qiita.com/matarillo/items/40fbdc4223689a1e6c43
- 参考:[C#]TaskクラスをJavaScriptのPromiseっぽく使ってみる実験 - Qiita
-
JavaScriptで非同期処理を順次実行する場合、
- 同期メソッド上で同期メソッドを順番に呼び出すのではなく、
- コールバックから再びコールバック付き非同期メソッドを呼び出す必要があるため、
コールバックのネストが深くなりコードが読み難くなるということがある。
-
しかし、Promiseを使用することで、この問題を解決することができる。
(シーケンシャルではなく、thenのメソッド・チェーンでコールバックを指定する)
組み込みクラス。
以下のようにPromiseオブジェクトを利用して非同期処理を実装する。
-
非同期処理関数はPromiseオブジェクトを返すように実装する。
-
Promiseオブジェクトは、非同期処理関数の中で以下のように生成される。
-
Promiseオブジェクトのコンストラクタに非同期処理の
「本体となる非同期処理関数」を(基本的に無名関数として)渡す。 -
この「本体となる非同期処理関数」は、
- 成功と失敗のコールバックを受け取る。
- そして、ajaxなどの非同期処理を実行して、
- 結果を受けて、thenメソッドに渡されたコールバックを実行する。
成功時:成功のresolveコールバックを実行する。
失敗時:失敗のrejectコールバックを実行する。
-
resolve, rejectコールバックに値を渡した場合、
この値は、後続の非同期処理に渡されるため、
後続の「本体となる非同期処理関数」で利用できる。
-
-
最初の非同期処理を呼び出す。
-
戻り値のPromiseオブジェクトのthenメソッドに引数に、
- 成功と失敗のコールバックを指定する。
- 更にthenメソッドでチェーンする場合、
成功と失敗のPromiseオブジェクトを返す非同期処理関数を指定する。
-
参考
- Promise.prototype.then() - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
- Promise.prototype.then() - JavaScript | MDN
- 従来型コールバック(JavaScriptのスレッド処理の該当節を参照)
従来型では、非同期処理を順次実行する場合、
非同期処理に非同期処理(コールバック)を渡すため、
以下の様に非同期処理がネストすることになる。
Promiseを使用すれば、
- thenや
- catch(例外をcatchし以降のrejectを止める)の
メソッド・チェーンで非同期処理を順次実行できる。
-
順次
var promise1 = fetchSomething1(); var promise2 = promise1.then(fetchSomething2); var promise3 = promise2.then(fetchSomething3); var promise4 = promise2.then(fetchSomething4); promise4.then(doSomethingFinally);
-
メソッド・チェーン
fetchSomething1() .then(fetchSomething2) .then(fetchSomething3) .then(fetchSomething4) .then(doSomethingFinally);
※ 各非同期処理(fetchSomething、doSomething)は、
Promiseオブジェクトを返すように実装されている。※ 各非同期処理に「値を渡したり」・「処理を追加したり」する場合は以下のようにする。
.then( function(rtn) { alert(rtn); return fetchSomething2(rtn); }).then(...
-
参考
- Promise.prototype.catch() - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch
- Promise.prototype.catch() - JavaScript | MDN
// 非同期処理関数はPromiseオブジェクトを返すように実装する。
var fetchSomething1 = function() {
// Promiseオブジェクトは、非同期処理関数の中で以下のように生成される。
return new Promise(
// Promiseオブジェクトのコンストラクタに非同期処理の
// 「本体となる非同期処理関数」を(基本的に無名関数として)渡す。
// この「本体となる非同期処理関数」は、成功と失敗のコールバックを受け取る。
function(resolve, reject) {
// そして、ajaxなどの非同期処理を実行して、
// 結果を受けて、thenメソッドに渡されたコールバックを実行する。
AsynchronousProcessingWrapper({
success: function(data) { // 成功した場合
// 成功のコールバックを実行する。
resolve('成功1');
},
fail: function() { // 失敗した場合
// 失敗のコールバックを実行する。
reject('失敗1');
}
});
}
// resolve, rejectコールバックに値を渡した場合、
// この値は、後続の非同期処理に渡されるため、
// 後続の「本体となる非同期処理関数」で利用できる。
);
};
// fetchSomething1 と同じ。
var fetchSomething2 = function(str) {
return new Promise(function(resolve, reject) {
AsynchronousProcessingWrapper({
success: function(data) { // 成功した場合
resolve(str + ' 成功2');
},
fail: function() { // 失敗した場合
reject(str + ' 失敗2');
}
});
});
};
fetchSomething1().then(function(rtn) {
alert(rtn);
return fetchSomething2(rtn);
}, function(error) {
alert('error:' + error);
return fetchSomething2(error);
}).then(function(rtn) {
alert(rtn);
}, function(error) {
alert('error:' + error);
});https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
※ ダミー非同期関数を削除した。
※ resolveをrejectに切り替えると動作を変更させることができる。
var fetchSomething1 = function() {
return new Promise(function(resolve, reject) {
resolve('成功1');
//reject('失敗1');
});
};
var fetchSomething2 = function(str) {
return new Promise(function(resolve, reject) {
resolve(str + ' 成功2');
//reject(str + ' 失敗2');
});
};
fetchSomething1().then(function(rtn) {
alert(rtn);
return fetchSomething2(rtn);
}, function(error) {
alert('error:' + error);
return fetchSomething2(error);
}).then(function(rtn) {
alert(rtn);
}, function(error) {
alert('error:' + error);
});-
同期処理と非同期処理を自然に混ぜて記述することが可能。
-
同期処理は、Promiseオブジェクト以外が返す。
この場合、戻り先で新しくPromiseオブジェクトが作成され、
返した値ですぐにresolve()が呼び出されるため、後続の非同期処理に渡すことができる。
以下で、並列処理を実装できる。
- Promise.all() - JavaScript | MDN
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
チェーンの最後にだけ、
「失敗のPromiseオブジェクトを返す非同期処理関数」
を設定すれば、ココでエラーをまとめてキャッチできる。
- Promiseでコールバック地獄から解放された話
https://www.slideshare.net/sotasugiura/slide-43304678 - Promiseによる非同期処理の書き方 - 30歳からのプログラミング
http://numb86-tech.hatenablog.com/entry/2017/01/02/152517
-
JavaScript
-
今更だけどPromise入門
https://qiita.com/koki_cheese/items/c559da338a3d307c9d88 -
Promiseについて0から勉強してみた
https://qiita.com/toshihirock/items/e49b66f8685a8510bd76 -
Promiseのpolyfill(IE11お前もか!) - Qiita
https://qiita.com/zERobYTezERo/items/ac458c4cf2a8f2f6c3dd -
Promise再入門 > ①
Promise基本編
https://qiita.com/gctfuji/items/1dfe4265c36bea903ab3 -
jQuery Deferredまとめ
https://qiita.com/hththt/items/9f193fc10b79cdeea903
-
連載 | ECMAScript 2015(ECMAScript 6)特集
https://html5experts.jp/series/ecma2015/-
Promiseで簡単!JavaScript非同期処理入門
-
-
future - Wikipedia
https://ja.wikipedia.org/wiki/Future -
Promise/Deferred パターン - 野次馬エンジニア道
http://notta55.hatenablog.com/entry/2014/09/20/144054 -
非同期処理とPromise(Deferred)を背景から理解しよう - hifive
https://www.htmlhifive.com/conts/web/view/study-room/async-programming-with-deferred
移行メモ
- 「戻る」の並びにある「Promise (JavaScript)」は自ページのため、 その旨を補ってプレーン・テキストとした。
- PukiWiki のページ内アンカ(
#xxxxxxxx)は GitHub Wiki では再現できないため、 同一ページ内のアンカは見出しから生成されるアンカに張り替え、 他ページのアンカを指すリンクは「〜(ページ名の該当節を参照)」の形に置き換えた。- 元 Wiki の行頭空白によるプレフォーマット・ブロックは、 フェンス付きコードブロックにした。
Tags: 移行, JavaScript, Promise, 非同期処理, コールバック地獄, then, catch, Promise.all, Deferred
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。