promiseがやっとわかった(気がした)ので投稿します。Pythonからはいった身としては、promiseのサンプルに出てくる即時関数が多くて理解しにくいと感じます(単に慣れていないだけですが)。そこで即時関数を使わずに理解しようと試みたという感じです。
大前提
そもそもpromiseとはなんのためにあるか、一度整理してみると
①2つの関数ex1とex2があって、非同期処理が含まれているときはどっちが先に終わるかわからない
②画像の読み込みだとそれでも問題がない(どっちが先に表示されてもok)
③しかし、データベースの読込のように、入力を待って処理をするように場合は困る。データがないのに処理を始めてしまうので
④そこでpromiseの登場。ex1の終了を待ってex2を開始する
イメージで捉える
まだピンとこない場合は、学芸会を思い受かべてみてください。
たとえば浦島太郎。亀がいじめられるシーンから始まります。非同期のままだと最初から浦島太郎が登場しちゃいます。うっかりするといじめ役と間違われるまである。浦島太郎が適切なタイミングで登場するようにするのがpromiseです。
stepごとに書いていきます
まず最初にPromiseのインスタンスをつくるところからになります。Promiseの正体はインスタンスで、引数にはexecutor関数(最初に実行させたい処理)を取ります。
const P1=new Promise(ex1) //Promiseの正体はインスタンスである。引数には関数(実行させたい処理)を取る。名前をex1とした
P1.then(ex2) //.then()も関数を引数に取る、引数は成功時に実行させたい関数である。名前をex2とした
つぎがex1関数(処理の中核です)
const ex1=(res,rej)=>{ //ex1関数は2つの引数(res, rej)を受け取る。resとrejもまた関数であり、ex1関数の中で実行される。
setTimeout(() => {
console.log("hello");
res("ok"); //res関数を実行するとPromiseは成功(fulfilled)状態,rej関数を実行するとPromiseは失敗(rejected)状態になる。
//resとrejは引数に値(例えばメッセージやデータ)を取る。この値をmesとするとmesは.then()や.catch()の引数に渡される。
}, 2000);
}
最後がex2関数(thenメソッドの中で実行されるやつです)
const ex2=(mes)=>{ //ex2は関数、P1のメソッドである.then()や.catch()の引数に渡される関数
console.log("then"+mes); //ex2関数の引数にはmesがわたってくるのでex2関数内で使える。
}
以下は上をまとめたpromiseの簡単なサンプルです。
const ex2=(mes)=>{ //ex2はPromiseインスタンスのメソッド console.log("then"+mes); //引数にはmesがわたってくる。
}
const ex1=(res,rej)=>{ //ex1関数は2つの引数(res, rej)を受け取る。
setTimeout(() => {
console.log("hello");
res("ok"); //resとrejもまた関数であり、ex関数の中で実行される。
//res関数を実行するとPromiseは成功(fulfilled)状態,ej関数を実行するとPromiseは失敗(rejected)状態になる。
//resとrejは引数に値(例えばメッセージやデータ)を取る。この値をmesとする
//mesは.then()や.catch()の引数に渡される。
}, 2000);
}
const P1=new Promise(ex1) //Promiseの正体はインスタンスである
P1.then(ex2) //.then()も関数を引数に取る
promiseのまとめ
Promiseの正体はインスタンスである。引数にはexecutor関数(実行させたい処理)を取る。
executor関数は2つの引数(resolve, reject)を受け取る。
resolveとrejectもまた関数であり、executor関数の中で実行される。
resolve関数を実行するとPromiseは成功(fulfilled)状態になる。
reject関数を実行するとPromiseは失敗(rejected)状態になる。
resolveとreject関数は引数に値(例えばメッセージやデータ)を取る。この値をmesとする
この値(例:メッセージ)はPromiseインスタンスのメソッドである.then()や.catch()の引数に渡される。
.then()も関数を引数に取る、この関数は成功時に実行させたい関数である。名前をex2とする
ex2関数の引数にはmesがわたされる。
比喩
私はオブジェクト指向をざっくり考えるときに学芸会モデルで考えています。
登場人物は主役や脇役のほかに、ただの木とか石ころのようにほとんど動かない役もあれば出番のタイミングを伝えるだけの裏方もいるといったイメージです。
またインスタンスと関数については
インスタンスは出番が終わっても前の状態を覚えていられるちょっと賢い子ども
関数は出番が終わるとすっかり忘れちゃう子ども
というイメージです。
これでいくと登場人物は5人です
ex1がいじめっこ役
ex2はメインの浦島太郎役
resはいじめのシーンが正常に終了したことを伝えるだけの役
rejは劇中に何らかのトラブルがあったことを伝える役
P1は全体の進行を管理して、浦島太郎に出番を伝える役
P1は「前の処理が今どういう状態なのか」を覚えている子。
だから then() に関数(ex2)を登録しておけば
「まだだよ(pending)」
「終わったよ(fulfilled)」
「失敗したよ(rejected)」
という状態に応じてex2を呼び出したり、とどまったりできる