Проблемы с отложенным объектом

У меня есть проблема, которую я пытаюсь решить, используя отложенные объекты в javascript (и я новичок в отложенных объектах).

Проблема: пользователь пытается запустить функцию (может быть много разных функций). Если функция не работает... она попытается снова войти в систему, а затем повторить попытку (один раз). Если авторизация не удалась. Ну тогда все терпит неудачу.

Эти функции и функция входа в систему содержат вызов Ajax, который будет возвращен.

Мой вопрос: могу ли я полагаться на то, что var dfd (в конце функции tryAjax) будет выполняться последним после того, как весь другой код в функции будет запущен?

Вот код:

function tryAjax(func)
{
    var dfd = new jQuery.Deferred();
    window[func]().then(
    function(p1,p2,p3)
    {
        //Everything worked great. No need to login.
        dfd.resolve(p1,p2,p3);
    },
    function()
    {
        //func failed
        //try to login user again before trying.
        loginUser().then(
        function()
        {
            //Login success
            //Try to run func again.
            window[func]().then(
            function(p1,p2,p3)
            {
                //Func succes after login
                dfd.resolve(p1,p2,p3);
            },
            function(p1,p2,p3)
            {
                //Func failed after login
                dfd.reject(p1,p2,p3);
            });
        },
        function(p1,p2,p3)
        {
            //Login failed
            dfd.reject(p1,p2,p3);
        });
    });

    return dfd;   
}

And to call it:
tryAjax('getData').then(
function(p1,p2,p3)
{
    //Success  
},
function(p1,p2,p3)
{
    //Error
});

person Juw    schedule 11.09.2012    source источник


Ответы (1)


Таким образом, вы хотите выполнить 3 отложенных последовательно и остановиться после первого успеха. Я бы использовал универсальную функцию, подобную этой:

function dfdSequence() {
  var deferred = jQuery.Deferred();
  var execute = function(functions) {
    var promise = functions[0].apply(functions[0], args);
    promise.done(function() {
      deferred.resolve();
    });
    if (functions.length === 1) {
      // It was the last call
      promise.fail(function() {
        deferred.reject();
      });
    } else {
      // Fail, let's move on the next function
      promise.fail(function() {
        execute(functions.slice(1, functions.length));
      });
    }
  };
  execute(Array.prototype.slice.call(arguments, 0, arguments.length));
  return deferred.promise();
}

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

dfdSequence(function() {
  // Your first login attempt
  return $.ajax(...);
}, function() {
  // Your second login attempt
  return $.ajax(...);
}, function() {
  // Your last login attempt
  return $.ajax(...);
}).then(function() { /* Success! */ }, function() { /* Failure */ });

РЕДАКТИРОВАТЬ: Ну, наверное, я неправильно понял вопрос. Как насчет этого фрагмента кода:

function getData() {
  return $.ajax(...);
}
function loginUser() {
  return $.ajax(...);
}
var deferred = jQuery.Deferred();
getData().then(function() {
  // Success
  deferred.resolve();
}, function() {
  loginUser().then(function() {
    getData().done(function() {
      deferred.resolve();
    });
  }, function() {
    deferred.reject();
  });
}
person Guillaume Poussel    schedule 12.09.2012
comment
Таким образом, вы хотите выполнить 3 отложенных последовательно и остановиться после первого успеха. Это зависит. Логика заключается в том, что вызов функции выполняется для универсальной функции, которая запускает функцию Ajax и возвращает (в данном случае getData(). Если это работает. Все должно закончиться. Если это не удается, он попытается вызвать функцию loginUser() (которая попытается войти в систему пользователя). Если эта функция не работает... все завершается ошибкой. Если она работает. Первая функция, которая была опробована, но не удалась (в данном случае getData()), будет запущена снова. Если она снова не удалась. ..все терпит неудачу ЕСЛИ это работает...тогда все хорошо. - person Juw; 12.09.2012
comment
Спасибо, что ответили и нашли время. Вы написали почти тот же код, что и я в моем исходном посте. Только у меня есть это в функции, и я использую window[func](), чтобы иметь возможность вызывать любую функцию (которая возвращает отложенный объект ajax для обработки). Но это поднимает вопрос. Могу ли я полагаться на то, что dfd будет возвращен ПОСЛЕ выполнения основного кода с отложенным... проверьте эту упрощенную функцию, которую я сделал, чтобы поднять проблему: stackoverflow.com/questions/12386728/ - person Juw; 12.09.2012