2016-01-06 2 views
0

В моей скрипке я следующая функцией, которая называется подтягивать (для имитации пользователя, начиная его три раза в быстрой последовательности)функция очереди не вызывает

https://jsfiddle.net/tvs1zdw9/1/

function test(){ 
    var r = $.Deferred(); 

    //simulate ajax call that loads data and takes 2 seconds 
    setTimeout(function(){ 
    r.resolve(); 
    count++; 
    $('#here>i').html(count); 
    },2000); 

    return r; 
} 

Цель: Независимо от того, как быстро пользователь продолжает нажимать кнопку, я всегда хочу дождаться завершения функции до ее повторного запуска.

Я уже добавил deferrer (г), что дает указание на, когда функция выполняется с помощью следующего кода:

test().done(function(){ 
    console.log('done running function'); 
}); 

Пример:

  • пользователь нажимает кнопку нажимает 3 раза быстрая последовательность
  • Функция называется три раза (быстрее, чем она может быть завершена)
  • Существует «Queu е», который создается
  • Следующий пункт в„очереди“пинают всякий раз, когда функция завершается, а не до

Я нашел функциональность очереди JQuery, но кажется, что это только для функций прикованных к элементам в DOM ... возможно, я не понимаю его полностью. Здесь: https://api.jquery.com/queue/

Может ли кто-нибудь помочь мне создать очередь, а затем пройти через нее после завершения каждой функции?

+0

Все они, если я запустить функцию 3 раза она должна работать в три раза, но синхронным. Поэтому он должен ждать, пока предыдущее время не пройдет через – DavidDunham

+0

, спасибо Аруну, но это просто «отключает» функцию до ее завершения. Я хочу, чтобы там была очередь – DavidDunham

+0

Почему бы не использовать .queue(), но прикрепить его к событию .click() на пустом div? Затем вы помещаете свою функцию внутри .click() и запускаете ее, как показано в JQuery API. – Cruiser

ответ

0

Решение: https://jsfiddle.net/jqqmrv4L/1/

Я создал переменную очереди

var queue = []; 

Когда функция вызывается до ее завершения я буду толкать в очереди.

var count = 0; 
    var running = false; 
    var queue = []; 
    var test = function(){ 
    var r = $.Deferred(); 

    if(!running){ 
     running = true; 

     //simulate ajax call that loads data and takes 2 seconds 
     setTimeout(function(){ 
     r.resolve(); 
     count++; 
     $('#here>i').html(count); 
     running = false; 
     },2000); 
    } else { 
     console.log('called whilst running'); 
     queue.push('234'); 
    } 

    return r; 
    } 

Тогда у меня есть еще одна функция для обработки очереди, которая вызывается после начальной функции завершил так:

test().done(function(){ 
     console.log('done running function, checking queue'); 
     runqueue(); 
    }); 

А вот последняя функция «runqueue», который обрабатывает очередь:

function runqueue(){ 
     if(queue.length){ 
      console.log('queue has!', queue.length); 
     //runqueue(); 
     test().done(function(){ 
      console.log('queue item completed'); 
      queue.splice(0,1); //delete this because it has ran 
      //runqueue(); 
     }); 
     } else { 
     console.log('queue done'); 
     } 
    } 
+0

К сожалению, это решение: (1) полагается на инвариантный, жестко закодированный 'test()', (2) неправильно отражает случай использования в вопросе (пользователь нажимает кнопку несколько раз подряд) (3) не показывает обработку ошибок. –

+0

1 hard-coded test() - это функция, вызываемая при нажатии кнопки – DavidDunham

+0

2 пользовательский ввод моделируется с помощью $ ('# userclick'). Trigger ('click'); который называется три раза в быстрой последовательности – DavidDunham

1

код может быть очень простым, даже элегантно, если вы реализуете:

  • очередь в виде цепочки обещаний
  • вещи, стоящие в очереди как функции.

Во-первых, функция многократного использования, которая формирует приватную очередь и возвращает функцию, посредством которой элементы могут быть добавлены в очередь.

function AsyncQueue(stopOnError) { 
    var p = $.when(); // a resolved promise, which acts as the seed of a .then() chain (ie a "queue"). 
    return function(fn) { 
     p = p 
      .then(null, function() { if(!stopOnError) return $.when(); }) // prevent propagation of a previous error down the chain. 
      .then(fn); 
     return p; 
    } 
} 

При этом, очередь (обещание цепи) будет «самоадминистрирование», так что потребность в running и runQueue() исчезает.

Теперь вы можете написать:

function goodDelay() { // simulate a successful request 
    return $.Deferred(function(dfrd){ setTimeout(dfrd.resolve, 1000); }); 
} 
function badDelay() { // simulate a failed request 
    return $.Deferred(function(dfrd){ setTimeout(dfrd.reject, 1000); }); 
} 

var queue = AsyncQueue(false); // `queue` is a function with its own private .then chain. 
queue(goodDelay).then(successHandler, errorHandler); 
queue(badDelay).then(successHandler, errorHandler); 
queue(goodDelay).then(successHandler, errorHandler); 

function successHandler() { 
    console.log('success:'); 
} 
function errorHandler() { 
    console.log('error:'); 
} 

stopOnError работает следующим образом:

  • ложных: внутренний обработчик ошибок гарантирует, что очередь всегда идет по пути успешного выполнения независимо от предыдущего результата ,
  • true: внутренний обработчик ошибок оказывается неэффективным, и очередь принимает естественное (jQuery) поведение распространения ошибки по цепочке. После ошибки дополнительные функции в очереди не будут срабатывать, хотя их внешние errorHandlers (если они есть) будут срабатывать, и все будут проинформированы об одной и той же «причине» отказа.

DEMO с stopOnError ложным
DEMO с stopOnError правда