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

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

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

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

jQuery

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

3回答

3960閲覧

jQueryで「$.when」の中で「if」を使いたい

nyoronyoronyoro

総合スコア6

JavaScript

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

jQuery

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2020/03/15 16:12

前提・実現したいこと

該当のソースコードで、「getB()」だけ「if」の中に入れたいと思っています。

このような分岐が目的です↓
if( double_actions === true ){ getB() }

該当のソースコード

jQuery

1get( double_actions ); // double_actions にはAとB2つとも実行するか否かのtruthyが入る 2 3function get( double_actions ) { 4 $.when( 5 getA(), 6 getB() // double_actions === true の場合だけ実行したい 7 ) 8 .then( function( A, B ) { 9 console.log( 'A=' + A ); 10 console.log( 'B=' + B ); 11 }) 12} 13 14function getA(){ 15 var deferred = new $.Deferred; 16 setTimeout( function() { 17 deferred.resolve( 'データA' ); 18 }, 500); 19 return deferred.promise(); 20} 21 22function getB(){ 23 var deferred = new $.Deferred; 24 setTimeout( function() { 25 deferred.resolve( 'データB' ); 26 }, 1000); 27 return deferred.promise(); 28} 29

試したこと

まず試したのがこうですが、「SyntaxError: expected expression, got keyword 'if'」というエラーで「if」が使えないようでした。

jQuery

1function get( double_actions ) { 2 $.when( 3 getA(), 4 if( double_actions === true ){ getB() } // エラー 5 ) 6 .then( function( A, B ) { 7 console.log( 'A=' + A ); 8 console.log( 'B=' + B ); 9 }) 10}

そして「if」を使う方法を調べているうちに以下の書き方を見つけました。しかしこれも同じエラーで「if」は使えないようでした。

jQeury

1function get( double_actions ) { 2 $.Deferred().resolve().then( function() { // ここを変更 3 return getA(), 4 if( double_actions === true ){ getB() } // エラー 5 }) 6 .then( function( A, B ) { 7 console.log( 'A=' + A ); 8 console.log( 'B=' + B ); 9 }) 10}

最終的に無理やりな気がしますがなんとか解決できたのが以下です。

これは「getB()」を実行しないのではなく、実行するけどすぐに「return」するという方法なのですが、かっこよさとしてはどうなのかなという気が致します。

jQuery

1get( true ); 2 3function get( double_actions ) { 4 $.when( 5 getA(), 6 getB( double_actions ) // ifはここではなく、この関数の中で判定する 7 ) 8 .then( function( A, B ) { 9 console.log( 'A=' + A ); 10 console.log( 'B=' + B ); 11 }) 12} 13 14function getA(){ 15 var deferred = new $.Deferred; 16 setTimeout( function() { 17 deferred.resolve( 'データA' ); 18 }, 500); 19 return deferred.promise(); 20} 21 22function getB( double_actions ){ 23 if( !double_actions ) return; // ここで判定する 24 var deferred = new $.Deferred; 25 setTimeout( function() { 26 deferred.resolve( 'データB' ); 27 }, 1000); 28 return deferred.promise(); 29}

上のコードでできたのならそれでいいだろという話かもしれませんが、もし「$.when」の中で「if」を使う方法があれば後学のためにご教授願えればと思い、ご質問を投稿させて頂きました。
すみませんがどなたかお知恵を拝借できませんでしょうか。

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

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

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

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

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

guest

回答3

0

$.when の引数に if を使えないのは、引数は式でないといけないのに、if は文だから、です。
式と文の違いについては、以下の記事をどうぞ。
参考: 文と式 · JavaScript Primer #jsprimer

JavaScript

1function get( double_actions ) { 2 $.when( 3 getA(), 4 if( double_actions === true ){ getB() } // エラー 5 ) 6 // 略

で、if のようなことを式でやるには、条件演算子というのが使えると思います。
参考: 【JavaScript入門】条件(三項)演算子の使い方と活用例まとめ! | 侍エンジニア塾ブログ(Samurai Blog) - プログラミング入門者向けサイト

JavaScript

1function get( double_actions ) { 2 $.when( 3 getA(), 4 double_actions ? getB() : undefined 5 ) 6 // 略

投稿2020/03/15 17:52

hoshi-takanori

総合スコア7901

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

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

nyoronyoronyoro

2020/03/16 10:02

式と文の違いも知りませんでした。条件演算子は式だから使えるわけですね。どうもありがとうございます。
guest

0

ベストアンサー

三項演算子で括るという案や即時実行関数を使えば解決しそうですね。
関数を作る際はIE11対応を行わないのならアロー関数の書き方が簡素でおすすめです

ポイントは$.when(fn, fn)をまるっとくくってしまうことでしょうか。

js

1// 三項演算子ルート 2function get( is_double_actions ) { 3 (is_double_actions 4 ? $.when(getA(), getB()) 5 : $.when(getA()) 6 ).then( function( A, B ) { 7 console.log( 'A=' + A ); 8 console.log( 'B=' + B ); 9 }); 10} 11 12// 即時実行関数(アロー関数) 13function get(is_double_actions) { 14 (() => { 15 if (!is_double_actions) return $.when(getA()); 16 return $.when(getA(), getB()); 17 })().then((A, B) => { 18 console.log( 'A=' + A ); 19 console.log( 'B=' + B ); 20 }); 21}

これは「getB()」を実行しないのではなく、実行するけどすぐに「return」するという方法なのですが、かっこよさとしてはどうなのかなという気が致します。

これ自体は「ガード節」という超優秀テクニックの一つです。
リーダブルコードという神書籍でも1章使って紹介されています。

今回のケースに限っていえば、
getBを実行すると決めたのなら実行しろよって話ですからそのガード節は微妙でしょうね。
この辺が質問文書いてる最中の違和感だと思います。


【おまけ】 そもそもdouble_actionsが微妙説

これ2個専用のコードなんですよね。
3個になったらどうすんねん。4個は?
この辺考えるとあまり良いコードではありません。

JavaScriptの全ての関数やメソッドはapplyメソッドを所持しています。
だからやるべき内容を配列にして所持しておき、applyを使って展開&実行という形に持っていくのが自然でしょう。

js

1// 欲しいactionは最初から配列形式でもっておく 2// actions = [getA(), getB()] 3function get(actions) { 4 $.when 5 .apply(null, actions) 6 .then(function (A, B) { 7 console.log( 'A=' + A ); 8 console.log( 'B=' + B ); 9 }); 10}

更におまけとして
ここまでくるとAやBという決め打ちのコールバック関数も微妙なのでオブジェクト形式で持たせてみます。

js

1// actions = {A: getA(), B: getB()} 2function get(actions) { 3 $.when 4 .apply(null, Object.values(actions)) 5 .then(functions(){ 6 var keys = Object.keys(actions); 7 for (var i = 0; i < arguments.length; i++) { 8 console.log(keys[i] + "=" + arguments[i]); 9 } 10 }); 11} 12 13function main (is_double_actions) { 14 var actions = {}; 15 actions.A = getA(); 16 if (is_double_actions) { 17 actions.B = getB(); 18 } 19 get(actions); 20}

このように配列を作ってfor文で一気に処理してしまうというのはめちゃくちゃ使えるテクニックなので検討してみてくださいね。

投稿2020/03/16 01:58

編集2020/03/17 02:11
miyabi-sun

総合スコア21203

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

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

nyoronyoronyoro

2020/03/16 10:23

大変丁寧に、しかも見本コードまでどうもありがとうございます。 まずforを使わない方を試させて頂きました。以下になるかと思ったのですが、CODEPENなどで実行しますとAB共にundefinedになってしまうようです。 どの記述が問題なのか、お手数ですが再度教えて頂けませんでしょうか。 main( true ); // 実行はget()でなくmain()にする function main (is_double_actions) { var actions = {}; actions.A = getA(); if (is_double_actions) { actions.B = getB(); } get(actions); } // 欲しいactionは最初から配列形式でもっておく // actions = [getA(), getB()] function get(actions) { $.when .apply(null, actions) // $.whenに対して.applyをかけると何が起こっているのでしょうか? .then(function (A, B) { console.log( 'A=' + A ); // "A=undefined" になってしまいます console.log( 'B=' + B ); // "B=undefined" になってしまいます }); } function getA(){ var deferred = new $.Deferred; setTimeout( function() { deferred.resolve( 'データA' ); }, 500); return deferred.promise(); } function getB(){ var deferred = new $.Deferred; setTimeout( function() { deferred.resolve( 'データB' ); }, 1000); return deferred.promise(); }
miyabi-sun

2020/03/17 02:08 編集

配列とオブジェクトの違いです。 例文のコードを混ぜてしまっているのが失敗の元です。 配列というのは`[getA(), getB[]]`のようなものを指します。 オブジェクトは`{A: getA(), B: getB()]`という風にキーと値がセットになったものを指します。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/apply JSの全ての関数が所持するapplyメソッドは第二引数で配列をくれと言っています。 これに配列ではなくオブジェクトを投げ込んでも当然動作はしません。 なのでObject.keys等を使いながらオブジェクトからキーの配列や、値の配列に変換しながら作業しています。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/keys --- > $.whenに対して.applyをかけると何が起こっているのでしょうか? $.whenというjQueryの関数は、`$.when(引数1, 引数2, 引数3....)`という風に可変長の引数を渡す作りになっています。 3つや4つに増えたらどうするねん!に対して最初から配列で持っておけという回答がありますが、 配列から`$.when(引数1, 引数2, 引数3....)`を実行するのはちょっと不可能ですよね。 そこで、JavaScriptのネイティブな機能として全ての関数・メソッドは`apply`メソッドを所持するルールになっています。 これを使うことで`$.when.apply(null, [引数1, 引数2, 引数3...])`という解決策が取れます。
miyabi-sun

2020/03/17 02:11

紛らわしかった&動かないコードだったので修正しましたよ。
nyoronyoronyoro

2020/03/18 13:01

ご修正ありがとうございます。たしかにObject.keysにしていただいたコードで機能しました。連想配列のキーを配列にしてくれるとは便利なメソッドですね。 .applyに関してのご説明もどうもありがとうございます。大変勉強になる数々のコメントに感謝申し上げます。
guest

0

Bにundefinedを返すことがマストでなければ以下でも

javascript

1 $.when( 2 getA(), 3 double_actions && getB() 4 ) 5

投稿2020/03/16 00:29

yambejp

総合スコア116724

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

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

nyoronyoronyoro

2020/03/16 10:04

ありがとうございます。そちらはどういう意味ですか?それを書くと左辺が真のとき、右辺が実行される?という意味ですか?「&&」は「かつ」だと思っていました。
miyabi-sun

2020/03/16 10:47 編集

JavaScriptに於けるイディオムの一つです。 イディオムってのは知る人ぞ知る必殺技みたいなテクニックを指しています。 JavaScriptに於ける`&&`は理解の通り「かつ」という意味ですが、 if文等の条件式に投げ込んでtrue or falseになる場合で挙動が変化します。 true: 左辺が真の場合、右辺評価して右辺を返す false: 左辺が偽なので、右辺を評価せず左辺をそのまま返す `double_actions && getB()`は、 `double_actions`がtrueならば`getB()`を返し `double_actions`がfalseならば右辺の`getB()`を返さず左辺を返すという挙動になります。
nyoronyoronyoro

2020/03/16 13:00

なるほど、ご説明ありがとうございます。理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問