jQuery AJAX:收集多个异步结果

时间:2009-11-04 17:16:47

标签: jquery ajax asynchronous

我正在对表单数据进行验证,这样当有人点击提交按钮时,它会首先检查表单的内容。许多字段(可能为零,可能不止一个,具体取决于页面)具有类似于需要先与服务器进行检查的唯一代码。我正在向服务器运行异步请求,该服务器只响应每个字段的“ok”或“taken”。如果任何字段有错误,则页面不会提交。

一方面,这应该是异步的:它应该在该请求处于关闭处理时继续验证其余的表单字段,包括触发其他请求。如果同步进行呼叫,则会明显降低后续字段的反馈速度。

另一方面,我想确保在对validate()方法回答“是”或“否”之前,所有验证请求都已返回(或超时),并允许提交继续进行。因此,如果有两个字段需要验证,则validate()方法应触发这两个AJAX请求,处理其余字段,然后等到这两个请求返回后再返回。

我可以通过一些丑陋的家庭式解决方案来实现这一点(可能涉及一组代表正在进行的请求的随机ID),但在我做之前是否有任何内置函数,插件或标准技术我应该使用代替?


澄清

我认为我需要的是在继续使用方法之前让代码等待来自一个或多个异步请求的结果。这与回调不同,因为方法的结果取决于请求的结果。它与同步请求不同,因为它们可能不止一个。

我在提交之前使用它来检查表单:

$("form").submit(function () {
    return validate($(this));
});

如果validate()方法返回false,则表单不会提交。 validate() hilights任何不被接受的字段。对于普通字段,validate()看起来像这样(非常简化的版本,没有反馈):

function validate(form) {
    resetWarnings(form);
    var ok = true;

    //  required fields
    form.find("input.required").each(function () {
        var field = $(this);
        if (field.val() === "") {
            ok = false;
        }
        return this; // meaningless in this case but a good habit to keep
    });

    //  fields that matches a pattern
    form.find("input.pattern").each(function () {
        var field = $(this);
        var pattern = field.data("pattern");
        if (!field.val().match(pattern)) {
            ok = false;
        }
        return this;
    });

    //  various other rules for other sorts of field
    ...

    return ok;
}

对于AJAX字段,它更像是:

    form.find("input.lookup").each(function () {
        var field = $(this);
        var url = field.data("lookup");
        $.ajax({
            url: url,
            data: { code: field.val() },
            success: function (result) {
                if (result === "taken") {
                    ok = false;
                }
            }
        }
    });

但是,当然,validate()已经在调用成功方法之前完成。因此,如果我可以让它等到ajax完成(成功或错误)返回之前,我可以得到正确的结果并停止提交表单。如果我使ajax同步,那么整个方法就会停止,直到完成,这是错误的。


进一步思考

鉴于Javascript的线程模型(也就是说根本没有),我在技术上要求的是什么?

3 个答案:

答案 0 :(得分:3)

使用jQuery 1.5+从多个异步请求中收集结果数据的最佳方法是使用表示这些请求及其状态的Deferred对象,以及包装函数$ .when(...)。then(allRequestsCompleteCallback(),someRequestFailedCallback ())

这有助于避免使用多个嵌套回调函数,使您的代码更清晰,更易于维护。

JavaScript / jQuery示例:

function ajax1() { return $.ajax({ url: 'server1.php' }) }
function ajax2() { return $.ajax({ url: 'server2.php' }) }

$.when( ajax1(), ajax2() ).then(
    function() {
        // ajax1 AND ajax2 succeeded
    },
    function() {
        // ajax1 OR ajax2 succeeded
    }
);

点击此处查看更多文档和示例:

答案 1 :(得分:1)

如果我理解正确,您需要检查表单中输入的值(1 .. *)是否唯一,一旦用户在表单上执行帖子之前点击提交按钮。如果是这种情况,我会创建一个字段和值的JSON数组并立即发送它 - 所以你只等待一个响应。使用jQuery“each”函数并使用jQuery ajax,这应该很容易。

然后,您可以在发布表单之前检查单个结果。

可能不言而喻,但请确保在发布后重复使用相同的验证服务器,以避免与其他用户竞争条件。

您可以在用户完成表单时验证单个字段,并存储结果,但这显然会更加繁琐(出于可扩展性的原因,您应该考虑带宽),并且您将更有可能在服务器端验证失败。

答案 2 :(得分:0)

如何使用.ajaxStop:

  $(document).ajaxStop(function() { 
    $(this).unbind("ajaxStop");
    // run validate method here
  }); 
  //run asynchronous validations here

请注意,如果validate()本身涉及AJAX调用,则需要unbind。