2016-04-15 7 views
0

у меня есть обработчик события переплетены в $someEl, который должен выполнять только тогда, когда oRes заполняется данными, которые могут исходить от любого первичного источника (getData1()) или источник резервного копирования (getData2()). Данные запрашиваются из источника резервного копирования только в том случае, если основной источник не работает.

Если первичный источник не тайм-аут, тогда все работает; однако, когда вызывается функция резервного копирования getData2(), dfd никогда не разрешается, поэтому ничто никогда не регистрируется при нажатии на $someEl. Я подозреваю, что он не работает, потому что объект Deferred в getData2() перезаписывает переменную dfd, на которую ссылается обработчик кликов $someEl.

У меня такое чувство, что я не применяю отсрочку/обещание с использованием шаблона «лучшей практики». Учитывая этот сценарий, как бы вы заставили обработчик щелчка правильно подождать, пока oRes не будет заполнен из основного ответа AJAX или вторичного ответа AJAX после таймаута?

Некоторые примечания для уточнения:

  • getData1() должен быть выполнен только после того, как документ будет готов
  • $someEl.click() может сработать в любой момент во время загрузки документа, поэтому обработчик события должен быть определен вне $(document).ready()
  • Я застрял с JQuery 1.7.1

Вот код:

var oRes, dfd; 

// Get data from primary source 
function getData1() { 
    dfd = $.ajax({ 
    ... 
    success: function(data) { 
     oRes = data; 
    }, 
    error: function(jqXHR, textStatus, errorThrown) { 
     if (textStatus==='timeout') getData2(); 
    }, 
    timeout: 10000 // 10-second timeout 
    }); 
} 

// Get data from backup source 
function getData2() { 
    dfd = $.ajax({...}); 
} 

$someEl.click(function() { 
    dfd.done(function() { 
    console.log('This should only log when oRes is ready'); 
    }); 
}); 

$(document).ready(function() { 
    getData1(); 
}); 

Я моделируется мое положение в этой ручкой: http://codepen.io/thdoan/pen/pyVyKj

По сути, у меня возникают проблемы при получении обработчика событий для вывода «Data готова!» когда oRes заполняется без необходимости вручную щелкнуть по полю после загрузки страницы.

+1

Просто хотелось бы отметить, что с вашей текущей стратегии, каждый раз, когда $ someEl щелкают будет связать другую функцию обратного вызова для отложенного объекта, поэтому при отсроченный окончательно решил, что он будет выполнять ваш обратный вызов X раз, где X - это количество раз, когда элемент был нажат. Это может быть вашим желаемым поведением, но просто хотелось убедиться, что вы знаете. –

+0

@MattDiamond спасибо за указание на это, очень хорошая точка :). Я изменил код, чтобы вместо этого использовать '.one ('click', ...)'. – 10basetom

ответ

0

Думаю, вам просто нужно поднять его на один уровень.

Создайте задержанный фронт, который ваш обработчик будет прослушивать (и этот экземпляр не изменится).

Вы затем решить, что отложенный либо из getData1() или getData2():

var oRes, 

    // Resolve this deferred when data has been successfully loaded: 
    dfd = $.Deferred(), 

    // But add listeners to this promise: 
    dfdPromise = dfd.promise(); 

// Get data from primary source 
function getData1() { 
    $.ajax({ 
     ... 
     success: function(data) { 
      oRes = data; 

      // Resolve when data loaded: 
      dfd.resolve(data); 
     }, 
     error: function(jqXHR, textStatus, errorThrown) { 
      if (textStatus==='timeout') getData2(); 
     }, 
     timeout: 10000 // 10-second timeout 
    }); 
} 

// Get data from backup source 
function getData2() { 
    $.ajax({...}) 
     .then(function(data){ 
      // Fallback data resolve: 
      dfd.resolve(data); 
     }); 
} 

$someEl.click(function() { 
    dfdPromise.done(function() { 
     console.log('This should only log when oRes is ready'); 
    }); 
}); 

$(document).ready(function() { 
    getData1(); 
}); 
+0

Спасибо Sly_cardinal, ваше решение сработало. Это был умственный горб, который мне нужно было преодолеть :-). Вот код: http://codepen.io/thdoan/pen/zqjBvp – 10basetom

+0

Обратите внимание, что он также работал без обещаний. – 10basetom

0

Я бы включил вызов функции в обратные вызовы запроса ajax.

var oRes = null; 
var dfd = null; 

// Get data from backup source 
function getData2() { 
    dfd = $.ajax({...}); 
} 

// Get the primary data source 
function getData1() { 
    dfd = $.ajax({ 
    success: function(data) { 
     oRes = data; 

     // set the click handler when oRes is successfully set 
     $(someEl).click(function() { 
      console.log('This should only log when oRes is ready'); 
     }); 
    }, 
    error: function(jqXHR, textStatus, errorThrown) { 
     if (textStatus==='timeout') getData2(); 
    }, 
    always: function(){ 
     if (oRes==null){ 
      getData2(); 
     } 
    } 
    timeout: 10000 // 10-second timeout 
    }); 
} 
+0

Я бы с удовольствием это сделал, к сожалению, я работаю с кодом, который является частью более крупного приложения, где $ someEl * можно * щелкнуть до '$ (document) .ready', поэтому его обработчик события должен быть определен вне его (и, следовательно, вне 'getData1()'). Я отредактирую вопрос, чтобы добавить ясность. – 10basetom

+0

Это не будет проблемой, потому что событие click назначается после загрузки javascript. Если DOM не закончил и пользователь нажимает, то они, скорее всего, попробуют снова, как только они увидят, что все загружено. – chriswirz

+0

chriswirz, я смоделировал свою ситуацию в этом ручке: http://codepen.io/thdoan/pen/pyVyKj - суть проблемы в том, что мне нужно вызвать щелчок на поле в начальной загрузке, но обещание не соблюдается или что-то еще блокирует первоначальную регистрацию. Я хочу, чтобы, когда oData заполняется, сообщение обработчика событий должно сказать: «Данные готовы!» без необходимости вручную щелкать по ящику. – 10basetom

 Смежные вопросы

  • Нет связанных вопросов^_^