2

Knockout を使用して完全に作成されたページがあります。テンプレートの 1 つで、リンクをクリックすると、日付を選択するための JQuery Datepicker コントロールが表示されます。日付を選択すると、選択した日付を使用して関数が実行され、Datepicker が閉じます。それだけでうまくいきます。

誰かが日付を選択してから Datepicker が閉じるまでに数秒かかる場合があります。これは、(LoadAppointmentTimeSlots) と呼ばれる関数が同期的に実行する必要があり、実行に時間がかかることが原因です。これに対処するために、システムが動作していることをユーザーにフィードバックする DIV を表示したいと思います ("#loading")。

問題は、LoadAppointmentTimeSlots 関数が実行されるまで (DIV が再び非表示になるまで) DIV が表示されないことです。いくつかの方法で setTimeout を試しましたが、何も機能しませんでした。

以下は「問題のある」コードです。

var SchedulingViewModel = function () {
  var self = this;
  ...
  self.Date_OnClick = function () {
    var selectedDate;
    $("#calendarPopup").append('<div  id="datepicker" />');
    $("#datepicker").datepicker({
      dateformat: 'mm-dd-yy',
      changeMonth: true,
      changeYear: true,
      setDate: new Date(),
      minDate: 0,
      maxDate: self.SelectedRFVInterval() - 1,
      onSelect: function (datetext, inst) {
        selectedDate = datetext;
        $("#loading").show();
        self.LoadAppointmentTimeSlots(datetext);  // function within view model that                 uses $AJAX in sync mode to return time slot data
        $("#loading").hide();
        $('#calendarPopup').dialog('close');
      }
    });
  };
  ...
}
4

1 に答える 1

1

あなたが直面している問題は、show() が非同期で実行され、javascript が単一のスレッドで実行されるため、すべての同期コード (LoadAppointmentTimeSlots など) が完了するまで待たなければならないことです。

希望する動作を得るには、show() 呼び出しの後のすべてを show コマンドのコールバックに入れます。そうすれば、show() 呼び出しが完了するまで LoadAppointmentTimeSlots は実行されません。方法は次のとおりです。

// ... other code
$("#loading").show(function() {
    self.LoadAppointmentTimeSlots(datetext);  
    $("#loading").hide();
    $('#calendarPopup').dialog('close');
});

ただし、LoadAppointmentTimeSlots の ajax 呼び出しを非同期に変更し、hide() および dialog('close') 呼び出しを ajax 呼び出しのコールバックに移動する方がよい場合があります。これにより、LoadAppointmentTimeSlots が終了するのを待っている間、javascript は他の処理を続けることができます。それは次のようになります。

// ... other code
$("#loading").show()
self.LoadAppointmentTimeSlots(datetext, function() {
    $("#loading").hide();
    $('#calendarPopup').dialog('close');
});
// ... more code


function LoadAppointmentTimeSlots(datetext, alwaysCallback) {
    // Prepare request details
    $.ajax( "/myendpoint?param=foo" )
      .done(function(data) { alert("success"); }) // do something with data 
      .fail(function() { alert("error"); })
      .always(alwaysCallback); // called on both success and failure of ajax call
}
于 2012-12-09T01:58:27.400 に答える