![]() |
この記事はちょっと愚痴っぽいです。 ←Promiseが分かりにくいと思った編集者のメモ書きなので、内容が不正確な場合があります。 |
JavaScript(ECMAScript)におけるPromiseとは、約束された未来非同期処理の成功または失敗を表すオブジェクトである。
といわれてもよくわからなかった編集者が、悩んだ点について、にわか仕込みの知識で述べる。分かっている人には当たり前のことかもしれないが、分かっていない人にとって非直感的で躓くのではないかというポイントを重点的に述べるつもりなので、通常とは説明の仕方がずれていたとしてもそれは仕様です。
通常プログラムは書いた順番に実行される。しかし非同期処理は書かれた順番に実行されるとは限らない。
これを無理やり制御しようとするとCallback Hellと呼ばれる深いネストが出来上がるが、ここでは触れない。
たいていの説明ではPromiseの内部の時間軸に焦点をあてて解説するのだが、そのせいで外部との関係が曖昧になっているように思う
前の処理
Promiseの処理
後の処理
Promiseのコンストラクタの説明に、new Promise()は内部の関数がresolve()されるまでPromiseの値が返らないというような説明をしていることがあるが、以下で述べる.then()が呼ばれないという意味であり、new Promise()の値が返ってから「後の処理」が行われるという意味ではない。
new Promise()の内部の関数処理は別の世界線時間軸に移動し、「後の処理」はPromiseの処理の進行状況とは無関係に進んでいく。
たいていの解説ではここでコンストラクタを出してくるが、Promiseのコンストラクタは、2つの関数を引数に取る関数を引数に取る関数という禍々しいものであるため、後回しにする。例外処理もできるのだが、本質でないので触れない。
Promise.resolve(初期値)
.then(function(初期値を受ける引数){処理1})
.then(function(処理1の戻り値を受ける引数){処理2})
.then(function(処理2の戻り値を受ける引数){処理3})
処理1、処理2、処理3が順番に実行されることが保証される。処理1、処理2、処理3は同期処理である?(Promiseを返してもいいらしい?)
Promiseのインスタンスは内部に.thenの引数となる関数に渡されるべき値を持っているが、この値をPromiseの外部で使う手段は提供されていない。内部で外部の変数に代入すれば持ち出せることは持ち出せるが、Promiseの内部と外部で時間の流れを同期させる方法がないため推奨されない?
Promiseのコンストラクタは、2つの関数を引数に取る関数を引数に取る関数という禍々しい高階関数であるが、あまり問題視されないのは、言語仕様だから仕方ないPromiseは通常コンストラクタで自作するものではなく、他のライブラリ関数から戻り値として渡されるものだかららしい。
これでは実行順序の制御が出来ないかのように見えるが、以下のようにするとPromiseの外部との間に順序をつけることができる。
let promise = new Promise(略)
let promise2 = promise.then(function(引数){処理1})
処理2
promise2.then(function(引数){処理3})
処理4
このやりかたが公式に推奨されるかどうかは知らない。
ただ、これで処理2が処理3より前に実行されることだけは保証される。
ただし、処理3と処理4の前後関係はthen()の内部はPromiseの時間軸で処理が進んでいくため、やはり前後関係が保証されないと思われる?
処理1が終わっていなくてもpromiseに処理3が追加されて処理4に進んでいくため、処理1が処理4よりも先に終了する保証もない?
promise(javascript)に関するニコニコ動画の動画を紹介してください。
[内容]
promise(javascript)に関するニコニコ市場の商品を紹介してください。
プロミスはモナドになっているのだが、あまりそのことについて考えてもメリットはない。モナドについて調べたことがあるのでせっかくだから書いておくが、モナドを知らないのならここは読み飛ばしたほうが身のためである。
unit()の関数の性質についてはモナド(プログラミング)を参照のこと。
多くのモナドではコンストラクタが、unit()に相当することが多いが、Promiseではコンストラクタはunit()ではない。Promiseが非直感的である理由の一つではないかと思う。
unit()に相当するのはPromise.resolve()である。
flatMap()の関数の性質についてはモナド(プログラミング)を参照のこと。
flatMap()に相当するのがthen()なのだが、then()が引数に取る関数が、flatMap()は一つだけなのに対し、then()はthen()呼ぶPromiseが成功していた場合と失敗していた場合2つの関数を引数に取る。一つの関数が内部でifを使って分岐していると思えば一つの関数かもしれない。
失敗を扱うという点がMaybeモナドに似たところがなくもない。
Promiseの内部で行った計算結果はPromiseの外には持ち出せない。値を取り出せるモナドも多いが、モナドでは本来値を取り出せることは保証されないものである。
Haksellはデフォルトで遅延評価な言語なので、もともと実行順序が制御できない。このような方法で実行順序を制御する必要はないのでPromiseに相当するモナドは重視されない。それでも実行順序の制御が必要な場合はdo記法がある。
急上昇ワード改
最終更新:2026/01/07(水) 18:00
最終更新:2026/01/07(水) 17:00
ウォッチリストに追加しました!
すでにウォッチリストに
入っています。
追加に失敗しました。
ほめた!
ほめるを取消しました。
ほめるに失敗しました。
ほめるの取消しに失敗しました。