🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

4回答

837閲覧

promise() を返さないのに $.when が有効な理由を知りたいです

kannmuri

総合スコア42

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

0クリップ

投稿2019/12/21 04:42

編集2019/12/21 07:13

###『前提』
次の$.whenの中には、myFadeOut()getAjaxData()という2つの関数があります。

2つの関数ではいずれもpromise()を返しています。(後述の『全体のコード』に掲載しています。)

だからこそ// 遅延処理が可能だと解釈しているのですが、質問があります。

js

1 $.when( 2 myFadeOut(area,1000), getAjaxData(100) 3 ) 4 .done(function(myFadeOutResult, ajaxData) { 5 // 遅延処理 6 }); 7

###『質問』
myFadeOut()を関数化せず次のように展開した場合にも// 遅延処理が可能なのはなぜですか?

展開するとpromise()を返していないのに、なぜ遅延が可能なのか?という理屈がわからないです。

js

1 $.when( 2 // myFadeOut() を展開し、promise() は返していない 3 $('section').fadeOut(1000, function(){ 4 var html = getHtml(area); 5 $('section').html(html); 6 }), 7 // getAjaxData() は展開せず関数で実行 8 getAjaxData() 9 ) 10 .done(function(myFadeOutResult, ajaxData) { 11 // 遅延処理 12 // promise() を返していないのになぜ遅延処理が可能なのか? 13 }); 14

###『全体のコード』
以下は『前提』の方に掲載した、展開前のコードの全体像になります。

ご覧の通りmyFadeOut()getAjaxData()proimse()を返しているのでこれは// 遅延処理が可能なのは当然だと思うのですが、

どうしてmyFadeOut()の方を『質問』のように展開し、proimse()を返していない場合でも可能なのか?

そのことについて教えて頂けましたらうれしく思います。

動くサンプル:https://jsfiddle.net/acbe51sd/

html

1<main> 2 <section> 3 <!-- Ajaxデータを反映したHTMLが挿入される --> 4 </section> 5</main> 6<button data-area="one">Pjax one</button> 7<button data-area="two">Pjax two</button>

js

1$('button').click(function(){ 2 const area = $(this).attr('data-area'); 3 Pjax(area); 4}); 5 6function Pjax(area){ 7 8 $('body').append('<p class="loading">loading</p>'); 9 10 $.when( 11 myFadeOut(area,1000), getAjaxData(100) 12 ) 13 .done(function(myFadeOutResult, ajaxData) { 14 console.log(ajaxData); 15 $('body').find('.loading').remove(); 16 $('section').find('div[data-area="'+area+'"]').html('<p>'+ajaxData+'</p>'); 17 $('section').fadeIn(1000, function(){ 18 //history.pushState(location.href); 19 }); 20 }); 21} 22 23function myFadeOut(area,dalution){ 24 const d = new $.Deferred; 25 $('section').fadeOut(dalution, function(){ 26 var html = getHtml(area); 27 $('section').html(html); 28 d.resolve(); 29 }); 30 return d.promise(); 31} 32 33function getAjaxData(delay){ 34 const d = new $.Deferred; 35 setTimeout(function(){ // テストのためAjaxの代わりにsetTimeOut 36 const ajaxData = 'Ajaxデータ'; 37 d.resolve(ajaxData); 38 }, delay); 39 return d.promise(); 40} 41 42function getHtml(area){ 43 let html; 44 if( area == 'one' ){ 45 html = `<div data-area="one"></div>`; 46 } 47 else if( area == 'two' ){ 48 html = `<div data-area="two"></div>`; 49 } 50 return html; 51}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ドキュメント jQuery.when() には確かに Deferred でも Promise でもなければ即時解決と書いてあります。
しかし、 .promise() の例に .promise() を呼ばずに $.when() で処理しているものがあり、$.when() に渡されたものが jQuery オブジェクトの場合は内部で .promise() 相当のことが処理されているものと思われます。
https://api.jquery.com/promise/#example-2

投稿2019/12/25 02:08

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2019/12/25 03:24

> 内部で .promise() 相当のことが処理されている コードを見る感じ、 // Check for promise aspect first to privilege synchronous behavior if ( value && typeof( method = value.promise ) === "function" ) { method.call( value ).done( resolve ).fail( reject ); とあるので、間違いないかと思います。 というか、jQueryオブジェクトであるかどうかをチェックしていないので、promiseをメソッドに持つオブジェクトならなんでも通ってしまいかねないですね。 https://github.com/jquery/jquery/blob/d0ce00cdfa680f1f0c38460bc51ea14079ae8b07/src/deferred.js
kannmuri

2019/12/25 04:01 編集

すみません!こちらのご回答に今気付きました。 .promise() 相当のことを処理してくれるのはいいですけど、それって .resolve() してやらないと先に進まないのでは? 『全体のコード』は .fadeOut() が終わってから .resolve() を返していますけど、『質問』のコードは .resolve() を返してはいないような気がするんですよね。
kannmuri

2019/12/25 04:01 編集

.resolve()は .promise() と同時に返しているということですか?
x_x

2019/12/25 04:09

自分で Deferred オブジェクトを作っているわけではないので .resolve() とかは不要です。 .promise() を読んでください。 https://api.jquery.com/promise/
guest

0

特に確認もしていませんが、Deferred や Promise 以外を渡したら「完了」と判断してdoneを実行するのでは。

【jQuery.when() | jQuery API Documentation】
https://api.jquery.com/jQuery.when/

If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately. The doneCallbacks are passed the original argument. In this case any failCallbacks you might set are never called since the Deferred is never rejected. For example:

投稿2019/12/21 07:53

kei344

総合スコア69596

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kannmuri

2019/12/21 07:57

ありがとうございます。「Deferred や Promise 以外を渡す」という処理はどこでやっているのでしょうか?
kei344

2019/12/21 08:00

「次のように展開した場合にも」のコードの最初の物はjQueryオブジェクトを渡していますが、それは「渡して」いないのでしょうか。
kannmuri

2019/12/21 08:12

「次のように展開した場合にも」のコードとはこれですね。 ~~~~~~~~~~ $.when( // myFadeOut() を展開し、promise() は返していない $('section').fadeOut(1000, function(){ var html = getHtml(area); $('section').html(html); }), // getAjaxData() は展開せず関数で実行 getAjaxData() ) .done(function(myFadeOutResult, ajaxData) { // 遅延処理 // promise() を返していないのになぜ遅延処理が可能なのか? }); ~~~~~~~~~~ このうち「jQueryオブジェクトを渡す」という処理がどれかわかりません。 たぶん getAjaxData() の返り値として .done() に ajaxData を渡している、ということかと思います。 でも fadeOut() の方は何も返せてませんよね?この処理を関数化した myFadeOut() であれば .resolve() として、 .done() に myFadeOutResult が返せてるかと思うのですが、でも関数化していないただの fadeOut() の方は、何をどうやって myFadeOutResult を返していると考えられるのでしょうか?
kei344

2019/12/21 08:26

var a = $('section').fadeOut(1000, function(){ var html = getHtml(area); $('section').html(html); }); としたらaにはjQueryオブジェクトが渡るのがわかりますか?
kannmuri

2019/12/21 08:37 編集

var a = $('.a'); console.log(a); としたとき、aに渡るのがjQueryオブジェクトである、ということでしょうか?わかります。 ということは、 var a = $('section').fadeOut(1000); console.log(a); としてもまったく同様のjQueryオブジェクトが渡っているということですか? なるほど、試したらたしかに同じでした。 ということは、上のaと同じ感じで .done() の myFadeOutResult に渡っている、と考えられるというわけですか!? …え?なんでです????笑
kannmuri

2019/12/21 08:41 編集

var a = としたからこそ、aにはjQueryオブジェクトが渡っているのだと思います。 しかし、それがない状態で、なぜ .done() の myFadeOutResult にaと同じ内容が渡せるのでしょうか? だってそのaの代わりをするための、myFadeOut() の d.resolve() ですよね?これがあるから myFadeOut() では値を渡せるというのはわかりますが… myFadeOut() を展開した状態で、 var a = も d.resolve() も どちらもないのになぜ渡せるのですか?
kei344

2019/12/21 09:06

> ということは、上のaと同じ感じで .done() の myFadeOutResult に渡っている、と考えられるというわけですか!? 違います。 var a = $('.a'); jQuery.when( a ); 上記のようになっていて、「Deferred や Promise 以外を渡している状態」です。
kannmuri

2019/12/21 09:19 編集

違いましたか!そうだと早合点してつらつら長文すみません。 なるほど、 var a = $('.a'); というのは jQuery.when( a ); という状態になっているんですね。 しかしだとしたら「getAjaxData() も展開した場合には、遅延処理ができなくなる」が説明つかなくなりませんでしょうか? つまり、こうして2つの関数を展開しますよね?するとできなくなるんです。 ~~~~~~~~~~ $.when( // myFadeOut() を展開し、promise() は返していない $('section').fadeOut(1000, function(){ var html = getHtml(area); $('section').html(html); }), // getAjaxData() は展開せず関数で実行 → ではなくこれも展開する setTimeout(function(){ const ajaxData = 'Ajaxデータ'; }, 100); ) .done(function(myFadeOutResult, ajaxData) { // 遅延処理 → できなくなる }); ~~~~~~~~~~ もし myFadeOut() の方で仰る仕組みで $('section') が返るのならば、 getAjaxData() の方でも ajaxData が返ってもいいと思うのですが… もし ajaxData はjQueryオブジェクトではなくてテキストだろ、というのでしたら、 const ajaxData = 'Ajaxデータ'; というテキストを const ajaxData = $('.test'); としても、やはり返りはしませんよね? なので関数化をやめて展開した場合に、 myFadeOut() の方では $('section') が返るのに、 getAjaxData() の方では $('.test') が返らない ということに、どうも合点がいかないです…(すみません)
kei344

2019/12/21 09:49

> var a = $('.a'); > というのは > jQuery.when( a ); > という状態になっているんですね。 違います。
kannmuri

2019/12/21 12:03

こりゃまたすみませんw 聞き方を変えると、getAjaxData() の方を展開したら遅延処理ができなくなるのに、myFadeOut() の方は展開しても大丈夫なのはどうしてですか??
kei344

2019/12/21 12:19

> getAjaxData() の方を展開したら遅延処理ができなくなる 展開の仕方に問題があるから。 myFadeOutは展開しても大丈夫ではなく、ただwhenと関係なく実行されるだけでは?
kannmuri

2019/12/21 12:27

う”-?難しいですね。 もし「whenと関係なく実行される」ということでしたら、次のコードでfadeOut(1000) の完了を待たずして .done の中の遅延処理が始まるのではないのでしょうか?? (2019/12/21 17:12と同じコードです) ~~~~~~~~~~ $.when( // myFadeOut() を展開し、promise() は返していない $('section').fadeOut(1000, function(){ var html = getHtml(area); $('section').html(html); }), // getAjaxData() は展開せず関数で実行 getAjaxData() ) .done(function(myFadeOutResult, ajaxData) { // 遅延処理 // promise() を返していないのになぜ遅延処理が可能なのか? }); ~~~~~~~~~~ あと、「展開の仕方に問題がある」とのことでしたら、「正しい展開」は思いつきますでしょうか?
kannmuri

2019/12/25 03:46 編集

つまり fadeOut は Deferred いらずで、myFadeOut() を展開した『質問』のコードは正しい書き方だったわけですか?
kannmuri

2019/12/22 00:13

また違ったこと言ってしまいましたか?
guest

0

// 遅延処理が可能なのはなぜですか?

うまくいきません。ajaxDatasetTimeoutにローカルなものになっていて、setTimeoutはコールバックの返り値をただ無視しますので、Ajaxの結果は取得できないはずです。

投稿2019/12/21 04:50

maisumakun

総合スコア145963

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kannmuri

2019/12/21 07:17 編集

すみません。展開するのは myFadeOut() の方だけで、getAjaxData() の方は展開しません。 質問文の『質問』のコードもそう修正しました。 その場合なら遅延処理は可能と思いますが、なぜでしょうか? getAjaxData() の方はその関数内で promise() を返していますが、 myFadeOut() の方は展開されていて promise() は返してないのに。
guest

0

jQueryの関数がDefferedしてくれるかどうかわからないなら
いまさらjQueryに固執せずにjsでpromise/async/awaitで
解決する方がよっぽど建設的だと思います

投稿2019/12/25 02:23

yambejp

総合スコア116661

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kannmuri

2019/12/25 03:17

ありがとうございます。結局『全体のコード』にある myFadeOut() を、『質問』のように展開することは、特に間違った書き方ではないという考えはあっているでしょうか?
yambejp

2019/12/25 03:21

ユーザー関数myFadeOutがDefferedしてresolve/promiseしている ロジックはあっていると思います
kannmuri

2019/12/25 03:35

んんと、『『全体のコード』にある myFadeOutの流れはあっているということですね? では『質問』の方はmyFadeOutがありませんが、こちらは間違っていますか?
yambejp

2019/12/25 03:45

$.whenはfadeOutのコールバックを待ちませんけど、 そういうことを聞きたいのでしょうか? <script> $(function(){ $.when( $('section').fadeOut(1000,function(){ $('div').fadeOut(1000); //これが実行される前にdoneされる }) ).done(function(){ console.log("done"); }); }); </script> <section>sec</section> <div>div</div>
yambejp

2019/12/25 03:48

中の処理を待たせるならqueue $(function(){ $.when( $('section').fadeOut(2000).queue(function(){ var _self=$(this); $('div').fadeOut(2000,function(){; _self.dequeue(); }); }) ).done(function(){ console.log("done"); }); });
kannmuri

2019/12/25 03:50 編集

>2019/12/25 12:45 え??待ってくれないんですか!?ほんとですね。 $.whenに渡したのがjQueryオブジェクト(今回の場合は「$('section')」であれば、なんやようわからんけど勝手になんとかしてくれるものと思っていましたw
kannmuri

2019/12/25 03:50

>2019/12/25 12:48 スゲェ!queueですか、調べてきます。
yambejp

2019/12/25 03:52

queueしたら適宜dequeueしないと処理が返ってこなくなるので 注意してください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問