質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

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

jQuery

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

Q&A

1回答

1188閲覧

jQueryの非同期処理が効かない(Deferred)

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2020/04/26 04:55

編集2022/01/12 10:55

前提・実現したいこと

動的に読み込んだ要素のロードが完了したら、高さを取得したい

発生している問題

ロード完了後のアラートがいつまで立っても表示されない

試したこと(console.log()追記)

qiitaの
https://qiita.com/scalewallet/items/939f16d3c85e0e0e5c65
を参考にして、自分の使いたい要素に合わせて改変してみました。
console.log()追記後のコンソールに表示された内容は

consoleLog

1step1 2step2-2 3step3

です。

html

1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>Document</title> 8</head> 9 10<body> 11 12 <div class="first"></div> 13 <script src="/js/jquery-3.4.1.min.js"></script> 14 <script> 15 function main() { 16 // DOMの操作は同期的に行われるため$.whenを利用する必要はない。 17 $('.first').append('<div class="hoge">hoge</div>') 18 19 // 追加されたそれぞれの要素をDeferred化し全てのロードが完了するのを$.whenで待つ 20 $.when.apply($, $('.hoge').map(waitForLoading)).then(function () { 21 alert("読み込み完了"); 22 }) 23 24 } 25 function waitForLoading(index, img) { 26 var dfd = $.Deferred(); 27 console.log("step1"); 28 29 // img要素のロード完了はimg.completeで取得できます。 30 if (img.complete) { 31 console.log("step2-1"); 32 // すでにロードが完了していれば即時resolve。 33 dfd.resolve() 34 } else { 35 console.log("step2-2"); 36 // ロードが完了していなかった場合、イベントリスナー登録しロードの完了を待つ 37 $(img).on('load', function () { 38 console.log("step2-2-1"); 39 resolve(); 40 }) 41 } 42 console.log("step3"); 43 return dfd; 44 } 45 main(); 46 </script> 47</body> 48 49</html>

###Deferredはdivのみのロードには効かないのか

長文にならないようにソースや説明を最低限のものに加工してたのですが、実は
①親ページに元からある「.first」に対して、動的にdiv「.parent」だけを挿入する
②挿入した「.parent」に対して、動的にiframeだけを挿入する
③「.parent」の中身をiframe中のターゲット「.my_content」のhtmlに書き換える(iframeタグ自体は消える)
④サイズを調節した後「.parent」の高さを取る
という流れを想定していました。

moyashidaisuke様のご回答で、Deferredを使った関数はdivだけの場合効かないと知ったので、
①部分はDeferredを使った関数を使わず、そのままappend致しました。
「.my_content」のhtmlは「<div class="my_content">子ページです。</div>」というdivだけなので
Deferredを使った関数は不要かと思ったのですが、
Deferredを使った関数(load_content)を利用してみたところ、divだけなのに作動しました。

divだけだとDeferredが効かない場合と、
divだけなのにDeferredが効く場合の違いは何でしょうか?

html

1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>親ページ</title> 8 <style> 9 *{ 10 box-sizing: border-box; 11 margin: 0; 12 padding: 0; 13 } 14 </style> 15</head> 16 17<body> 18 19 <div class="first"></div> 20 <script src="/js/jquery-3.4.1.min.js"></script> 21 <script> 22 (function () { 23 24 25 function load_iframe() { 26 var deferred = $.Deferred(); 27 var iframe = $('<iframe class="my_iframe" src="child.html"></iframe>'); 28 iframe.on('load', deferred.resolve); 29 iframe.prependTo('.parent'); 30 return deferred.promise(); 31 } 32 33 function load_content(html) { 34 var deferred = $.Deferred(); 35 var load_page = $(html); 36 load_page.on('load', deferred.resolve); 37 $('.parent').html(html); 38 return deferred.promise(); 39 } 40 41 $('.first').append('<div class="parent"></div>'); 42 43 44 var iframe_height; 45 46 47 $.when(load_iframe()).then(function () { 48 49 iframe_height = $('.my_iframe').contents().find('.my_content').outerHeight(); 50 console.log("iframeのターゲットコンテンツの高さ=" + iframe_height); 51 var html = $('.parent .my_iframe').contents().find('.my_content').prop('outerHTML'); 52 console.log(html) 53 load_content(html); 54 55 56 }).then(function () { 57 console.log("読み込み完了"); 58 /*サイズを色々変えてみた後に高さ取得*/ 59 $('.parent').css("padding-top", "100px"); 60 $('.parent').css("height", 100 + iframe_height + "px"); 61 console.log("親の高さ=" + $('.parent').outerHeight()); 62 63 }); 64 65 66 67 }()); 68 </script> 69</body> 70 71</html>

html

1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>子ページ</title> 8</head> 9 10<body> 11 12 <div class="my_content">子ページです。</div> 13 14</body> 15 16</html>

consoleLog

1iframeのターゲットコンテンツの高さ=24 2<div class="my_content">子ページです。</div> 3読み込み完了 4親の高さ=124

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

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

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

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

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

m.ts10806

2020/04/26 04:56

waitForLoading() はどこまで実行できているのでしょう。 console.log()など入れてデバッグしてください。
退会済みユーザー

退会済みユーザー

2020/04/26 08:43

コメントありがとうございます。 「試したこと(console.log()追記)」という見出しの章に追記致しました。
guest

回答1

0

参考にされたqiitaの記事は、jQueryで追加したimgの画像が読み込み完了したら〜、という処理です。

今回追加している要素はdivのみですので、非同期で読み込む対象が無いため、waitForLoadingは効きません。

appendした次の行で高さを取得すれば動くと思います。

投稿2020/04/26 06:16

moya_dev

総合スコア183

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

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

退会済みユーザー

退会済みユーザー

2020/04/26 08:44

コメントありがとうございます。 divだけだとDeferredが効かない場合と、 divだけなのにDeferredが効く場合の 違いを検証したのですがわからなかったので追記致しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問