Подтвердить что ты не робот

Как связать последовательность отложенных функций в jQuery 1.8.x?

Учитывая эти функции:

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

  setTimeout(function() {
    dfd.resolve('Password');
  }, 1000);

  return dfd.promise();
}

function func2(message) {
  var dfd = $.Deferred();

  setTimeout(function() {
    if (message == 'Password') {
      dfd.resolve('Hello World');
    }
   }, 1000);

  return dfd.promise();
}

Я хотел бы найти лучший способ сделать следующее. Обратите внимание, что это использование jQuery 1.8.x.

var promise = func1();

promise.done(function(message1) {

  var promise2 = func2(message1);

  promise2.done(function(message2) {
    alert(message2);
  });
});

Любые идеи? Я думал, что использование jQuery #pipe или #then будет работать, но я не могу понять это. Вот скрипка для игры: http://jsfiddle.net/Z7prn/

4b9b3361

Ответ 1

Это не так сложно (используйте .then или .pipe, они оба одинаковы с jQuery 1.8, я думаю).

promise.then(func2).done(function(message) {
    alert(message);
});

Так как func2 возвращает новый отложенный объект, вместо него обращается обратный вызов .done.

DEMO

Ответ 2

У меня был аналогичный вариант использования, поэтому я думаю, что это должно помочь вам.

Следующий метод примет массив методов (который может возвращать или не возвращать Promises) и выполнять их последовательно, ожидая завершения каждого отложенного до его продолжения. Поведение по умолчанию - это остановка при сбое; второй аргумент позволяет вам продолжить работу, если вызов завершился неудачно или нет.

Подписи

done/fail handler (Array <context> ) Функция (Array < Object {reject | resolved: arguments} > ), где контекст является контекстом каждого разрешенияWith/rejectWith вызова или отложенного вопроса и аргументов это набор аргументов, который был передан в разрешении/отклонении.

(function ($) {
    "use strict";
    var copy = function (a) {
        return Array.prototype.slice.call(a);
    };

    /**
        Handle a sequence of methods, stopping on failure by default
        @param Array<Function> chain    List of methods to execute.  Non-deferred return values will be treated as successful deferreds.
        @param Boolean  continueOnFailure   Continue executing even if one of the returned deferreds fails.
        @returns Deferred
     */
    $.sequence = function (chain, continueOnFailure) {
        var handleStep, handleResult,
            steps = copy(chain),
            def = new $.Deferred(),
            defs = [],
            results = [];
        handleStep = function () {
            if (!steps.length) {
                def.resolveWith(defs, [ results ]);
                return;
            }
            var step = steps.shift(),
                result = step();
            handleResult(
                $.when(result).always(function () {
                    defs.push(this);
                }).done(function () {
                    results.push({ resolved: copy(arguments) });
                }).fail(function () {
                    results.push({ rejected: copy(arguments) });
                })
            );
        };
        handleResult = continueOnFailure ?
                function (result) {
                    result.always(function () {
                        handleStep();
                    });
                } :
                function (result) {
                    result.done(handleStep)
                        .fail(function () {
                            def.rejectWith(defs, [ results ]);
                        });
                };
        handleStep();
        return def.promise();
    };
}(this.jQuery));

Простой пример использования: http://jsfiddle.net/rG9rA/

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

  setTimeout(function() {
    dfd.resolve('Password');
  }, 1000);

  return dfd.promise();
}

function func2(message) {
  var dfd = $.Deferred();

  setTimeout(function() {
    if (message == 'Password') {
      dfd.resolve('Hello World');
    }
   }, 1000);

  return dfd.promise();
}

    $.sequence([func1, func2, function () { alert('done'); }]);

Ответ 3

Используйте JQuery.when(). Это именно то, что вы хотите связать массив отложенных событий и запустить функцию, когда все будет сделано.

Обновление 2017 (после просмотра downvotes):

То, что OP хотел, было лучшей версией его кода для последовательного запуска promises. Вот моя версия, используя $.when:

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

  setTimeout(function() {
    dfd.resolve('Password');
  }, 1000);

  return dfd.promise();
}

function func2(message) {
  var dfd = $.Deferred();

  setTimeout(function() {
    if (message == 'Password') {
      dfd.resolve('Hello World');
    }
   }, 1000);

  return dfd.promise();
}

// ~~~~~~~~~~ using $.when here ~~~~~~~~~~~~

$.when(func1()).then(function(result1) { 
    $.when(func2(result1)).then(function(result2) {
        alert(result2);
    }) 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>