javascriptのPromiseネストがヤバい時の治し方

製作 プログラム

最終更新日:2022/05/11

ラムネグから一言:寝る前に読むとくだらなすぎて逆に寝れると好評なすごい適当なブログをこっちではじめてます.

javascript個人的にあんまり好きじゃないんですよね。

なんていうかたぶん見様見真似でやってるからすんごい汚いソースコードになっちゃうのが苦手で…。

さて。javascriptにはPromiseっていう仕組みがあります。

これを使うとAjaxの応答を待ってから続く処理に移れたりと、「これやってからこれやってね!」っていう直列?処理ができるようになります。

んでもPromiseを連続で使う、例えば「まずこれやって!んでそれ済んだらこれね!あ、その後はこれで、その次は…」とかやってるとPromiseの中にPromiseがnewされて、またそのPromiseの中でPromiseがnewされて…、とものすごいネスト地獄になりますよね。というかぼくの書き方が下手すぎてなっちゃったんです。

今回はこのjavascriptのPromiseネスト地獄を解決する方法を書きたいと思います。

先に関数を宣言しておこう

Promiseがネストになっちゃう原因の一つはやっぱりPromiseの中(厳密にはPromiseの後のthenの中)で新しいPromiseを作るせいだと思います。

こうなると一人目のPromiseのthenの中で2人目のPromiseが生まれて、そのthenでまた新しいPromiseが爆誕して…、となります。普通にifでネスとしてるよりthenが入ってる分めちゃめちゃみづらいんですよね。

てことでこうしたらいいよ!っていうのを。


const Promise1 = function(){
	return new Promise((resolve, reject) => {
		ajaxInit(resolve, reject);
	});
}
const Promise2 = function(){
	return new Promise((resolve, reject) => {
		ajaxSend(resolve, reject);
	});
};
const Promise3 = function(){
	return new Promise((resolve, reject) => {
		ajaxLoad(resolve, reject);
	});
}

まず最初にこんな風にPromiseにしたい関数を宣言しておきます(個人的にアローたくさんな書き方はよくわかってないんですが参考にした記事がこの書き方だったんでこうなってます。「new Promise(function(resolve,reject){…});」で書いてもOK)。

わざわざ「return new」にしてるのは、こうしておかないとPromiseは宣言したタイミングでその中身をすぐ実行しちゃうので、先に関数を宣言(んで実行はさせない)、っていうのができないため。

あとajaxInitとかは別途私が作った関数なのでそんなのは普通はないです。

ajaxInitとかにresolveとrejectを送ってて、んでajaxInitとかでajax通信をした最後のdone()のところでresolve()呼ぶ感じです。んでそのdone()でのresolve()を待って次の処理に移る、と。

今回はajaxInitのdoneを待って、ajaxSend、そしてajaxLoadをPromiseで直列処理するイメージを持ってもらうとわかりやすいと思います。

参考:ajaxInit概要

イメージが湧きづらいカモ…?という事でajaxInitの中身の概要をサクッと。

var ajaxInit = function(resolve, reject){
	$.ajax({
		url      : ○○,
		type     : 'GET',
		dataType : 'json',
		data:{
			'id'    : id,
		}
	})
	.done( (data) => {
		resolve(data);
	});
}

Ajaxではサーバーから応答があるとdone()が実行されるので、そのタイミングでPromiseからもらってきたresolveを呼べばようやっと次の処理に進むというワケ。

んで続いて実際にPromiseの連鎖?部分はこんな感じ。


Promise1().then(() => {
	return Promise2();
}).then(() => {
	return Promise3();
});

すごい見やすくなりましたよね!(今回エラー処理catchの方は書いてないんでアレなんですが…)

thenの中でそれぞれPromise2やらPromise3をreturnしてるのがどうやらキモみたいです(javascriptは感覚でやっちゃってるんで説得力がなくてスミマセン)。

Promise2やらPromise3の返り値をここで見てみると、「return new Promise…」となっています。つまりPromiseオブジェクトを返している、と。

んでPromiseのthenはPromiseオブジェクトを返り値にもらうことでチェーン処理が可能になる、らしいです。

てことで一つめのthenで帰ってきたPromiseオブジェクトの終了(resolve)を待ち、そして次のthenへ…、という動く、と。

もちろんここから4つ目5つ目とチェーンをつなげることも可能だし、さらに言うと次のthenに送りたいデータがあるならresole(data)として、then(data)と書いておけば次のthenの中でそのdataが使えます。

まとめ

今回はjavascriptのPromiseでネスト地獄になっちゃうときの治し方を紹介しました。

まとめると先にPromiseしたい処理を宣言して置いて、それを後からPromiseチェーン?で繋げてあげればみやすくなります。

…うーん、にしてもjavascriptは表記がたくさんあってなじめないんですよね。関数一つ宣言するのも「function honyarara」って書くやり方や「var honyarara = function」って書くやり方、それからアロー演算子みたいなのたくさん使う簡易記法みたいなのがあって…。

そんなんだからついつい、動けばいい!になっちゃうんですよね~。よくないですね。

【おしらせ、というか完全なる宣伝】

文体がもうぜんぜん適当すぎてあれだけどものすごい自由に書いてるブログ「檸檬だくだく」もよろしく.寝る前に読める恐ろしくくだらないやつです.

こんなにも一ミリも目を引かれないタイトルを取り扱ってます: ココア20g / ハイチュウとかってさ / なぜ米と小麦を食べようと思ったのかの謎 /