前提・実現したいこと
jQuery で以下のような
API【A】へリクエスト、そのレスポンス値を使って
API【B】へリクエスト、そのレスポンス値を使って
オブジェクトに格納し、 return
でデータを渡せるようなものを書いています。
jQuery の Deferred や when / then による同期的な記述をしていますが
以下の記述だと、最終的な return
が同期的に返せておらず、
どの記述が良いか、ご教授、アドバイスをいただけると嬉しいです。
発生している問題・エラーメッセージ
該当のソースコードの ※ の部分が同期的に return が取れず困っている箇所です。
該当のソースコード
javascript
1$(function() { 2 3 'use strict'; 4 5 function parent () { 6 7 // 最終的に `parent` を外のjsから実行した時の return に利用したい 8 var result = []; 9 10 // childBの処理で利用したい配列。中身はchildAで作成する 11 var useB = []; 12 13 // APIのURL 14 var jsonA = 'https://www.hoge.jp/apiA.php'; 15 var jsonB = 'https://www.hoge.jp/apiB.php'; 16 17 function childA () { 18 19 // 同期を取るため延期させるDeferredオブジェクト作成 20 var d = new $.Deferred(); 21 22 // Ajax 23 $.ajax({ 24 url: jsonpA, 25 dataType: 'jsonp', 26 jsonpCallback: 'jsonpA', 27 cache : true, 28 }) 29 .then( function( res ) { 30 31 // 取ってきたマニュアル jsonp を eachで回して 32 $( res ).each( function (index, el) { 33 34 // childBで利用するためのデータを格納 35 useB.push({ el.hoge }); 36 37 }); 38 39 useB = useB.join(); 40 41 // Deferred 延期の解決 42 d.resolve(); 43 44 }); 45 46 // プロミス作ってDeferredを返す 47 return d.promise(); 48 49 } 50 51 function childB () { 52 53 // 同期を取るため延期させるDeferredオブジェクト作成 54 var d = new $.Deferred(); 55 // Ajax 56 $.ajax({ 57 url : jsonB, 58 dataType : 'jsonp', 59 jsonpCallback : 'jsonB', 60 cache : true, 61 }) 62 .then( function ( res ) { 63 64 // ここで 最終的に return で利用したいデータを蓄積する 65 $( useB ).each( function (index, el) { 66 67 // 足していく 68 result.push({ 69 'test01' : el.element01, 70 'test02' : el.element02 71 }); 72 73 }); 74 75 // Deferred 延期の解決 76 d.resolve(); 77 78 }); 79 80 // プロミス作ってDeferredを返す 81 return d.promise(); 82 83 } 84 85 // childAを実行してchildBを実行 86 $.when( 87 88 childA() 89 90 ) 91 .then(childB) 92 93 // ※ ここに書いても結局 when then を待たず時実行される。。同期的ではない 94 return result; 95 96 } 97 98 // windowオブジェクトに追加して外部jsから呼び出せるようにする 99 window.parent = parent(); 100 101});
これを読み込んだ後に別のjs(またはhtml上で)で parent
として呼び出して利用しています。
試したこと
上記だと、 $when
/ then
から外れた所で return
を書いているので同期的にならないと考え以下のように記述したのですが、
その場合、 function parent
の return
としては扱われないので、困りました。
javascript
1$(function() { 2 3 'use strict'; 4 5 function parent () { 6 7 // 最終的に `parent` を外のjsから実行した時の return に利用したい 8 var result = []; 9 10 // childBの処理で利用したい配列。中身はchildAで作成する 11 var useB = []; 12 13 // APIのURL 14 var jsonA = 'https://www.hoge.jp/apiA.php'; 15 var jsonB = 'https://www.hoge.jp/apiB.php'; 16 17 function childA () { 18 19 // 同期を取るため延期させるDeferredオブジェクト作成 20 var d = new $.Deferred(); 21 22 // Ajax 23 $.ajax({ 24 url: jsonpA, 25 dataType: 'jsonp', 26 jsonpCallback: 'jsonpA', 27 cache : true, 28 }) 29 .then( function( res ) { 30 31 // 取ってきたマニュアル jsonp を eachで回して 32 $( res ).each( function (index, el) { 33 34 // childBで利用するためのデータを格納 35 useB.push({ el.hoge }); 36 37 }); 38 39 useB = useB.join(); 40 41 // Deferred 延期の解決 42 d.resolve(); 43 44 }); 45 46 // プロミス作ってDeferredを返す 47 return d.promise(); 48 49 } 50 51 function childB () { 52 53 // 同期を取るため延期させるDeferredオブジェクト作成 54 var d = new $.Deferred(); 55 // Ajax 56 $.ajax({ 57 url : jsonB, 58 dataType : 'jsonp', 59 jsonpCallback : 'jsonB', 60 cache : true, 61 }) 62 .then( function ( res ) { 63 64 // ここで 最終的に return で利用したいデータを蓄積する 65 $( useB ).each( function (index, el) { 66 67 // 足していく 68 result.push({ 69 'test01' : el.element01, 70 'test02' : el.element02 71 }); 72 73 }); 74 75 // Deferred 延期の解決 76 d.resolve(); 77 78 }); 79 80 // プロミス作ってDeferredを返す 81 return d.promise(); 82 83 } 84 85 // childAを実行してchildBを実行 86 $.when( 87 88 childA() 89 90 ) 91 .then(childB) 92 .then(function(){ 93 // ※ ここで return させても `parent` の return としては扱われない。。 94 return result; 95 }) 96 97 } 98 99 // windowオブジェクトに追加して外部jsから呼び出せるようにする 100 window.parent = parent(); 101 102});
どうぞよろしくお願いします。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/08/21 08:18 編集
2018/08/21 08:53