使用deferred with jquery ajax调用和异步进程以及用户确认读取

时间:2012-11-05 14:43:08

标签: jquery asynchronous jquery-deferred decoupling

背景
这是我的问题Correct way to set up a sequence of synchronous/asynchronous functions all of which can stop form submission and further processing?

的延续

我得到的答案是正确的方法(延期管道),但我仍然无法实现这一点。我今天刚开始阅读关于jquery延迟API的文章,但我还是掌握不了多少。 jQuery API文档似乎过于复杂,只有很少的例子。任何人都可以链接到一些关于此的基本演示/教程吗?我需要在这里启动。

详情
我在这个项目中使用了jquery 1.6版。

考虑这个例子 - 当用户点击表单提交按钮时 -
1.运行validateInventory()。
   一个。如果验证失败,如果用户同意,则向用户显示确认对话框(转到步骤2)
   或
   湾如果验证通过(转到步骤2)
2.运行preValidateUrls()。
   一个。如果验证失败,如果用户同意,则向用户显示确认对话框(转到步骤3)
   或
   湾如果验证通过(转到步骤3)
3.提交表格。

以下是我所拥有的异步函数的结构 -

请注意,此函数内部还有一个if(确认)块。阅读我的问题2

    function validateInventory()
    {
         $.ajax({
           type: "POST",
           url: posturl+"?"+params,
           dataType: "json",
           success: function(res)
               { 
                     if(!res.success)
                     {
                          //display some confirmation dialog, if user agrees con
                          if(confirm(msg)) 
                          {
                                //continue with next validation step 
                          }
                     }  
                     else
                     {
                          //validation success - so continue with next validation step
                     }  
                }
            });
    }

    //similar logic as inside validateInventory()
    function preValidateUrls()
    {


    }

我可能还在验证逻辑中有一些同步验证函数(仅客户端逻辑),序列中的任何位置 -

function syncVal()
{
    return true/false
}

问题1 这些函数的语法是否也应该与异步函数类似?

问题2 如何处理显示确认对话框的显示(如果验证失败),并且仅在用户确认时才进入下一个验证步骤。应该对功能进行一些重组吗? if(confirm)块需要移到外面吗?

我到目前为止

没什么,我想我需要使用.when.done API。

1 个答案:

答案 0 :(得分:1)

如果我正确理解了步骤1,2,3,那么您想要的逻辑可以编码如下:

$(function() {
    function validateInventory(form) {//`form` is passed conventionally at the left hand end of the pipe chain.
        var dfrd = $.Deferred();//A Deferred object to be resolved/rejected in response to ajax success/error.
        var params = .....;//use values from `form` as required
        $.ajax({
            type: "POST",
            url: posturl + "?" + params,
            dataType: "json"
        }).done(function(res) {//ajax success
            if(res.success || confirm(msg1)) { dfrd.resolve(form); }//Here we resolve dfrd, passing `form` in order to make `form` available to the next function in the pipe chain.
            else { dfrd.reject("validateInventory() failed (not verified)"); }//Application error. By rejecting with a specific message, we have the means of knowing where the failure occurred.
        }).fail(function(jqXHR, textStatus, errorThrown) {//ajax error
            dfrd.reject("validateInventory() failed (textStatus)");//Again, a specific message.
        });
        return dfrd;
    }

    //Similar logic as inside validateInventory()
    function preValidateUrls(form) {//The form, is piped through by the statement `dfrd.resolve(form);` in validateInventory
        var dfrd = $.Deferred();
        var params = .....;
        $.ajax({
            type: "POST",
            url: posturl + "?" + params,
            dataType: "json"
        }).done(function(res) {
            if(res.success || confirm(msg2)) { dfrd.resolve(form); }
            else { dfrd.reject("preValidateUrls() failed (not verified)"); }
        }).fail(function(jqXHR, textStatus, errorThrown) {
            dfrd.reject("preValidateUrls() failed (textStatus)");
        });
        return dfrd;
    }

    //This is the function to be called if the various stages of validation were successful.
    function overallSuccess(form) {
        form.submit(); 
    }

    //This is a common error handler, which will be called if either of the validation stages fail.
    function errorHandler(message) {
        alert(message);//or whatever
    }

    var myForm = $("form").get(0);//for example

    //And now the glue that puts the component parts together.
    validateInventory(myForm).pipe(preValidateUrls, errorHandler).pipe(overallSuccess, errorHandler);
});

未测试

有关说明,请参阅代码中的注释。

整个事情可以用任何不同的方式来考虑。我会选择像上面那样对它进行编码,因为组件部分是独立且清晰的,“胶水”语句(管道链)非常简洁,易于扩展以适应进一步的验证步骤。使用其他方法,您往往会深入嵌入难以理解的函数,特别是对于将来必须维护代码的人。