2017-01-06 22 views
1

私は、ユーザがそれを押したときに追跡したいボタンを持っており、追跡ajaxコールがデータを返す場合は約束を実行し、すべて完了したらボタンイベントを続行します。ネストされた約束関数

以下は私がこれまで持っていたものですが、ボタンイベントと第2の約束は同時に発生します。ボタンイベントが待っていないAJAXはハロー警告し、その後、質問を返さない場合は第二約束は解決するために

  • クリックボタン
  • AJAX呼び出しがイベント
  • を記録します。
  • AJAX呼び出しで質問が返された場合は、モーダルを閉じてモーダルを開いてから、helloを呼び出します。
$('.my_button').on('click', function() { 
    ui_tracking('button_1').then(function() { 
     alert('Hello'); 
    }); 
}); 

function ui_tracking(type, payload) { 
    var deferred = $.Deferred(); 

    var log_action = function() { 
     $.ajax({ 
      url: '/api/submit_action', 
      type: 'POST', 
      dataType: 'json', 
      data: { 
       type: type, 
       payload: JSON.stringify(payload) 
      }, 
      success: function(results, textStatus, xhr) { 
       if (typeof(results) !== 'undefined' && results !== null) { 
        if (typeof(results.data) !== 'undefined' && results.data !== null) { 
         if (results.data.question) { 
          startQuestion(results.data.question).then(function() { 
           deferred.resolve(); 
          }, function() { 
           deferred.reject(); 
          }); 
         } 
        } 
       } 

       deferred.resolve(); 
      }, 
      error: function (xhr, textStatus, errorThrown) { 
       deferred.reject(); 
      } 
     }); 
    }; 

    log_action(); 

    return deferred.promise(); 
} 

function startQuestion(question_data) { 
    var deferred = $.Deferred(); 

    var openQuestion = function() { 
     $('#question-modal .modal-body .question').html(question_data.question).attr('data-question-id', question_data.id); 

     $('#question-modal').modal('show').on('hidden.bs.modal', function (e) { 
      deferred.resolve(); 
      $('#question-modal').unbind('hidden.bs.modal'); 
     }); 
    }; 

    openQuestion(); 
    return deferred.promise(); 
} 

SF

+0

私はあなたがjavascriptの[Promise.all](HTTPSが必要だと思う:// developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)の機能です。 –

+0

@PabloDarde - 約束が一連のものであるように、Promise.allは役に立たない。 –

答えて

0

あなたの成功:コールバックは(もし条件の後、最後に)すぐdeferred.resolve();を呼び出し

success: function(results, textStatus, xhr) { 
     if (typeof(results) !== 'undefined' && results !== null) { 
      if (typeof(results.data) !== 'undefined' && results.data !== null) { 
       if (results.data.question) { 
        startQuestion(results.data.question).then(function() { 
         deferred.resolve(); 
        }, function() { 
         deferred.reject(); 
        }); 
       } 
      } 
     } 
     // this gets called regardless of the above conditions! 
     deferred.resolve(); 
(jQueryの)約束を返しアヤックス

知っ$、私はあなたが次のようにui_tracking関数を単純化できると信じています:

function ui_tracking(type, payload) { 
    return $.ajax({ 
     url: '/api/submit_action', 
     type: 'POST', 
     dataType: 'json', 
     data: { 
      type: type, 
      payload: JSON.stringify(payload) 
     } 
    }).then(function(results) { 
     if (results && results.data && results.data.question) { 
      return startQuestion(results.data.question); 
     } 
    }); 
} 
上記.thenで

、条件が満たされない場合、リターンはundefinedです...基本的にあなたがdeferred.resolve()でやっていたのと同じもの - アヤックスしかし

を完了すると返された約束がundefinedに解決されます条件がすべて満たされている場合、戻り値はstartQuestionで返されます。返されたPromiseはstartQuestionによって返されます。したがって、あなたのコードは解決する約束を待ってから続行します。

また、単に拒否された約束を返すエラー処理の必要はない - 外部呼び出しがエラーを処理するようにする

また、あなたが

$('.my_button').on('click', function() { 
    ui_tracking('button_1') 
    .then(startQuestion) 
    .then(function() { 
     alert('Hello'); 
    }); 
}); 

function ui_tracking(type, payload) { 
    return $.ajax({ 
     url: '/api/submit_action', 
     type: 'POST', 
     dataType: 'json', 
     data: { 
      type: type, 
      payload: JSON.stringify(payload) 
     } 
    }); 
} 

function startQuestion(results) { 
    var deferred; 
    var openQuestion = function (question_data) { 
     $('#question-modal .modal-body .question').html(question_data.question).attr('data-question-id', question_data.id); 

     $('#question-modal').modal('show').on('hidden.bs.modal', function (e) { 
      deferred.resolve(); 
      $('#question-modal').unbind('hidden.bs.modal'); 
     }); 
    }; 
    if (results && results.data && results.data.question) { 
     deferred = $.Deferred(); 
     openQuestion(results.data.question); 
     return deferred.promise(); 
    } 
} 

として全体の多くを書くことができます確かにロジックが約移動したので、多分あなたは

+0

アヤックスの約束を使って私に完璧に働いた。最後の書き換えは私の最高のものではありません。これは多くの場所や物事を統合しようとしているImに適用する必要があるからです。説明もありがとう! – seesoe

0

が欲しい、まさにあなたは返す関数内の各「ステップ」をカプセル化することができません約束(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)し、それらを「連鎖」する。

これは、直列に約束を実行に大きな柱である:http://www.datchley.name/promise-patterns-anti-patterns/#executingpromisesinseriesは(あなたが用ポリフィルを必要とするかもしれないあなたの有望:https://github.com/stefanpenner/es6-promise

関連する問題