JQuery отложен. Использование $.when и .progress()

Пишу парсер, заваленный асинхронными задачами. Я использую промисы JQuery для контроля и упорядочения асинхронных задач. Это псевдокодовая версия функции-конструктора:

   /**
     * @constructor
     */
    function Parser(json)
    {   
        return $.when(
            this.delete().then(this.insert(json)),
            this.doSomething(),
            this.doSomethingElse().then(this.update(json))
        ) 
    };

и вот как выглядит пример функции:

Parser.prototype.doSomething = function()
{   
    var dfd = $.Deferred();

    exampleTask(dfd.reject, dfd.resolve);

    return dfd.promise();
};

Из документов JQuery:

В случае, когда несколько объектов Deferred передаются в jQuery.when, метод возвращает Promise из нового «главного» объекта Deferred, который отслеживает совокупное состояние всех объектов Deferred, которые он передал.

Как я могу использовать .progress() для уведомления всех, кому небезразличен общий прогресс парсера? например

var parser = new Parser(json);
parser.progress(function(prog){console.log(prog});

Вот скрипка с тем, что я пытаюсь сделать: http://jsfiddle.net/ashanova/RjULA/2/


person Jon Wells    schedule 22.08.2012    source источник


Ответы (1)


Используйте deferred.notify() для вызова progressCallbacks. Например:

function doSomething() {   
    var dfd = $.Deferred();

    var count = 0;
    var intervalId = setInterval(function() {
        dfd.notify(count++);
        count > 3 && clearInterval(intervalId);
    }, 500);

    return dfd.promise();
};

var promise = doSomething();

promise.progress(function(prog) {
  console.log(prog);
});​

ДЕМО.

person João Silva    schedule 22.08.2012
comment
Я понял, как использовать .notify внутри функции (как в вашей демонстрации), но я хочу передать его обратно в конструктор и уведомить оттуда об общем прогрессе. Я хочу посмотреть, что делает синтаксический анализатор в целом, а не его функции — если вы будете следовать за мной? - person Jon Wells; 22.08.2012
comment
@CrimsonChin: Не уверен, правильно ли я понял ваш вопрос, но в этом случае вам нужно будет создать и сохранить ссылку на $.Deferred в вашем конструкторе, чтобы вы могли вызывать notify в каждом методе. Что-то вроде этих строк: jsfiddle.net/B7nzy - person João Silva; 22.08.2012
comment
это гораздо ближе! Я подумал, что если $.when создал мастер, отложенный, то, возможно, я мог бы уведомить о прогрессе непосредственно этому - person Jon Wells; 22.08.2012
comment
@CrimsonChin: $.when создает не $.Deferred, а Progress, поэтому вы можете вызвать для него notify. Также обратите внимание, что вы можете выполнить то же самое, передав в конструктор простую функцию обратного вызова: jsfiddle .net/Fubq4. - person João Silva; 22.08.2012
comment
Хороший вопрос о обратном вызове, возможно, я слишком усложняю его? Имейте в виду, это именно то, для чего предназначено уведомление. В итоге я сделал это: jsfiddle.net/ashanova/HMStX/7. Как вы думаете? - спасибо кстати - person Jon Wells; 22.08.2012
comment
Выглядит неплохо! Хотя кто-то менее знакомый с $.Deferred может не понять, что есть главный отложенный для уведомления о ходе выполнения и обычный отложенный для каждой задачи. - person João Silva; 22.08.2012
comment
@JoãoSilva $.when создает не $.Deferred, а Promise, поэтому вы не можете вызвать для него уведомление FTFY - person Fabian Schmengler; 08.02.2013