Использование jQuery отложено для отправки формы, только если проходит серия процессов

Во-первых, я признаю, что завладеть API deferred pipe в последнее время было для меня самой сложной задачей.

Требование

Я хотел бы отправить форму, если серия проверок пройдена.

  • Некоторые из них будут функциями с синхронной проверкой на стороне клиента, а некоторые — асинхронными проверками, выполняющими вызов AJAX. Асинхронные функции возвращают логическое значение обратного вызова.

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

  • Форма должна быть отправлена ​​только в том случае, если все отдельные блоки возвращают (или выполняют обратный вызов) true.

Добавлено позже. Асинхронные функции могут содержать вызовы ajax внутри некоторых условий, поэтому в некоторых случаях вызов ajax может не выполняться.

  • Внутри асинхронных функций может быть проверка подтверждения пользователя внутри кода обработки ответа AJAX.

Ниже приведены структуры моих функций -

function synchronousMethod()
{
  //some logic
  return (confirm("user input"));
}

function aSynchronousMethod1(callback)
{

   if(condition)
   {
        //ajax call
        callback(bool); //does callback true/false
   }
   else
   {//some use cases may follow this path and not make the AJAX call at all. 
        return true;
   }
}

Ниже приведен один из моих экспериментов с $.Deferred (может быть, я делаю это совершенно неправильно)-

$.when( synchronousMethod(), aSynchronousMethod1(),aSynchronousMethod2())
.done(function() {
    //I want to submit my form if all the functions returned/called-back true
    console.log("submitting form");
})
.fail(function() {
    console.log( 'I fire if one or more requests failed.' );
});

Но текст «отправка формы» выполняется до завершения асинхронной функции, и любые функции также вызывают эту ошибку TypeError: callback is not a function.

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

$.when( synchronousMethod, aSynchronousMethod1,aSynchronousMethod2) Но ни одна из функций не выполняется.

Обновить

Другой подход

Я также пробовал что-то подобное, но у меня были такие же проблемы, как и при первом подходе -

var promise = defer.pipe(synchronousMethod);
promise = promise.pipe(aSynchronousMethod1); 
promise = promise.pipe(aSynchronousMethod2);
promise = promise.pipe($("form#frmCampaigns").submit());

Обновление 2 Добавлено еще два пункта —

  • Асинхронные функции могут содержать вызовы ajax внутри некоторых условий, поэтому в некоторых случаях использования вызов ajax может не выполняться.

  • Внутри асинхронных функций может быть проверка подтверждения пользователя внутри кода обработки ответа AJAX.

Обновлена ​​структура асинхронной функции -

function aSynchronousMethod1(callback)
{
        //some sync logic here
    if(condition) /*some condition*/
    {
        //ajax call
        if(ajax sucess response)
        {
             callback((confirm("If user accepts"));
        }
        else
        {
        callback(false);
        }
    }
    else
    {//some use cases may follow this path and not make the AJAX call at all. 
        callback(true);
    }
}

person Sandeepan Nath    schedule 24.05.2013    source источник
comment
Привет, Sandeepan, мне любопытно, почему вы используете $.deferred для проверки формы? Если вы используете jQuery, почему бы просто не использовать обычный $.post и не отображать следующий блок в случае успешного обратного вызова?   -  person supermasher    schedule 24.05.2013


Ответы (1)


Я не уверен, что полностью понимаю ваш пример. Но я думаю, что проблема может заключаться в том, что ваши асинхронные методы должны возвращать обещание (например, возвращаемое значение $.ajax):

function sync() {
    return "something";
}

function async1() {
    return $.ajax("http://www.foo.com");
}

function async2() {
    return $.ajax("http://www.bar.com");
}

$.when(sync(), async1(), async2()).done(function() {
    console.log("success");
}).fail(function() {
    console.log("error");
});

Вот рабочий пример: http://jsfiddle.net/CcsQz/

Обновить

Да я вижу. Может быть, вы можете сделать что-то вроде этого в вашем случае:

function syncOrAsync(sync, confirm) {

    var deferred = jQuery.Deferred()

    if (sync) {
        deferred.resolve();
    } else {
        $.ajax('http://www.foo.com').done(function(data) {
            if (confirm(data)) {
                deferred.resolve();
            } else {
                deferred.reject();
            }
        }).fail(function() {
            deferred.reject();
        });
    }

    return deferred.promise();
}

var confirm = function(data) {
    // check confirmation here

    return true;
}

var method1 = syncOrAsync(true, confirm);
var method2 = syncOrAsync(false, confirm);

$.when(method1, method2).done(function() {
    console.log('done');
}).fail(function() {
    console.log('fail');
});

Обновленная скрипта: http://jsfiddle.net/mKdwN/

person Michael Weiss    schedule 24.05.2013
comment
Спасибо за ответ. Но у меня ситуация немного сложнее. Пожалуйста, проверьте раздел Обновление 2 в моем вопросе. - person Sandeepan Nath; 24.05.2013