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

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

ただいまの
回答率

87.49%

【JavaScript】非同期制御が出来ない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,650

score 7

B.jsにおいてはajaxの非同期制御は可能ですが、A.jsからB.jsを呼び出した際ににA. jsで非同期制御が出来ない状態です。
(doneの箇所にB.jsの実行が完了する前に到達してしまう。) 

when~doneの記載方法に問題があるのか不明な状況です。 
対応方法についてご教示頂きたいです。 



A.js
function test(){ 
    $.when( 
        test.search.textSearch('test', 1, null, null, null) 
     ).done(function(data_a) { 
        return data_a; 
     }); 


B.js
test.search = (function() { 
    // テキスト検索 
    var textSearch = function(search, pageNo, treeNo, id, column) {
    params = {"search": search, 
                    "pageNo": pageNo, 
                    "treeNo":treeNo, 
                     "id":id
         }; 
     $.ajax({ 
        type: "POST", 
        url: 'search/testSearch', 
        data: params, 
        dataType: 'jsonp', 
        jsonpCallback: 'callback', 
    }).done(function(json){ 
        if(json.data && json.data.length ! = 0) { 
            return json.data; 
        } 
    }); 
}; 


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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

B.jsの下の部分が切れているようですので、その部分で何かしらしているのかもしれませんが、提示されている状態で終了だとすると、そもそもtest.searchがundefinedなので、test.search.textSearch('test', 1, null, null, null) でエラー起こしていませんか?

test.search.textSearchで実行させたいならB.jsは下記のような感じになるかと思います。
test.search = (function() {
  return {
    // テキスト検索
    textSearch: function(search, pageNo, treeNo, id, column) {
      params = {
        "search": search,
        "pageNo": pageNo,
        "treeNo":treeNo,
        "id":id
      };
      $.ajax({
        type: "POST",
        url: 'data.json',
        data: params,
        dataType: 'json',
        jsonpCallback: 'callback',
      })
      .done(function(json){
        if(json.data && json.data.length !== 0) {
          return json.data;
        }
      });
    }
  };
})();

 jQuery.when

jQuery.when()
jQuery.when( deferreds )
deferreds
Type: Deferred
One or more Deferred objects, or plain JavaScript objects.
公式ドキュメントではこのようになっています。
また、こちらの例 jQuery.DeferredとかjQuery.whenの使い方について ではjQuery.whenは下記のようになっています
var hoge = $.ajax({
    url : "~" ,//{"text" : "hoge"}を返すAPIとする
    type : "GET",
    dataType : "json"
});

var fuga = $.ajax({
    url : "~" ,//{"text" : "fuga"}を返すAPIとする
    type : "GET",
    dataType : "json"
});

$.when(hoge, fuga).done(function(data1, data2){
    console.log(data1[0].text); //hoge
    console.log(data2[0].text); //fuga
});

その上で実行しようとしていた関数test.search.textSearchを見てみると、普通のfunctionですので、A.jsの$.when()内で呼び出したtest.search.textSearchがundefinedを返して終了した段階で、done()が実行されます。
$.when()内で呼び出した関数のAjaxの処理が完了してからdone()に進めたい場合は、呼び出す関数がDeferred objectsを返すようにしなければダメかと思います。
問題のコードの場合は $.ajax()をreturnしてしまえば良いかと思います。
// B.js
test.search = (function() {
  return {
    // テキスト検索
    textSearch: function(search, pageNo, treeNo, id, column) {
      params = {
        "search": search,
        "pageNo": pageNo,
        "treeNo":treeNo,
        "id":id
      };
      // ajaxをreturnする
      return $.ajax({
        type: "POST",
        url: 'data.json',
        data: params,
        dataType: 'json',
        jsonpCallback: 'callback',
      })
      .done(function(json){
        if(json.data && json.data.length !== 0) {
          return json.data;
        }
      });
    }
  };
})();
※ ただし、ajaxを返す方法だとB.jsのajax完了時に恐らくdeferred.resolveが自動的に実行されるのでしょう。A.jsのdone()で受け取れる引数data_aは returnで指定されたjson.data ではなくjson になります。

 jQuery.when().done()に加工した引数を渡したい場合

Ajaxで取得した値を加工して渡したい場合はtest.search.textSearchはdeferred.promise()を返して、deferred.resolve()を使って引数を渡すようにする必要があるかと思います。
// B.js
test.search = (function() {
  return {
    // テキスト検索
    textSearch: function(search, pageNo, treeNo, id, column) {
      params = {
        "search": search,
        "pageNo": pageNo,
        "treeNo":treeNo,
        "id":id
      };
      var defer = $.Deferred();
      $.ajax({
        type: "POST",
        url: 'data.json',
        data: params,
        dataType: 'json',
        jsonpCallback: 'callback',
      })
      .done(function(json){
        if(json.data && json.data.length !== 0) {
          // defer.resolve を使ってA.jsのdone()に引数を渡す
          defer.resolve( json.data );
        }
      });
      // defer.promiseを返す
      return defer.promise(this);
    }
  };
})();

 jQuery.when()を使わなくても良いかも。

こうするとtest.search.textSearch()はDeferred Objectを返しちゃっているので、A.jsで複数の非同期書処理を行いたいのでなければ、jQuery.whenを使わずに単純に下記のように書いてしまってもOKです。
// A.js
function test(){
  test.search.textSearch('test', 1, null, null, null)
   .done(function(data_a) {
      return data_a;
   });
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/17 21:15

    分かり易い回答ありがとうございました。
    会社で確認後、実際に試したところ動作出来ました。

    キャンセル

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

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る