使用AJAX实现回调/延迟对象

时间:2014-06-19 22:41:19

标签: javascript jquery ajax callback deferred

以下是用户单击表单上的“保存”按钮时调用的函数。当PreSaveAction函数返回true时,将提交表单。如果返回false,则不会发生任何事情。我在这里使用AJAX调用来验证表单值,并且如果validateUniqueStaff成功则希望PreSaveAction返回true,如果失败则反之亦然。

function PreSaveAction() { 
    $.ajax({
        url: listUrl,
        type: "GET",
        dataType: "json",
        success: validateUniqueStaff,
        error: function (data) {
            alert("Error: Problem with the AJAX request");
        }  
    }); 

    //if (validateUniqueStaff succeeds) return true, else return false
}

我的麻烦在于我无法弄清楚如何在此处合并延迟对象。我已尝试同步运行ajax调用,这适用于Chrome,但不适用于IE8(需求)。

我绝对难过。任何建议都将非常感谢!如果我能提供任何其他信息,请告诉我。

3 个答案:

答案 0 :(得分:1)

实际上可能!

您需要使用开发人员工具(F12)来获取按钮后面的当前java脚本代码。

以下是如何继续:

    //1. unbind the current handler:

         var saveButton = ...;   //your id (looks like ctl00_***)
         var saveButtonCallBack = ...; //call back id (looks like ctl00$...)

    //2. When document is ready

        jQuery(saveButton).unbind('click').click(function(){

                    PreSaveActionPeter(

                        function (){        
                            WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(saveButtonCallBack, "", true, "", "", false, true))
                        }
                    ) 
                });

    //3. Define your function:

        function PreSaveActionPeter(callBack)
            {
                jQuery.ajax({
                    url: *your url*,
                    method: "GET",
                    headers: {
                        "accept": "application/json;odata=verbose",
                    },
                    dataType: "json",
                    success: function (data) {
                        if (data.d.results.length > 0) {
                            callBack();
                        }
                    },
                    error: function (XMLHttpRequest, textStatus, errorThrown) {
                        alert(XMLHttpRequest.responseText);
                    }
                });     

                return true;
            }

//4. Override of the default PreSaveAction

function PreSaveAction()
    {       
        return false;
    }

答案 1 :(得分:0)

您的PreSaveAction()是异步的。您无法从该函数返回成功或失败值。它将在ajax调用完成之前返回很长时间。

对于异步调用(例如Ajax调用),您必须在稍后调用的回调中处理结果。您不能假装使用异步操作的同步编码技术。它不会起作用。 PreSaveAction()在ajax调用完成之前很久就返回,因此它的返回值将不知道Ajax调用的最终结果。

如果您的SharePoint环境要求PreSaveAction()返回true/false并且您需要执行Ajax操作以确定是否应该返回truefalse,那么你陷入困境。您可以使Ajax调用同步,但这通常是一种糟糕的用户体验,因为它在Ajax调用期间锁定了浏览器,如果您要跨域,则无论如何都无法进行同步。


最好的解决方案是了解PreSaveAction()函数的选项,看看是否可以将回调函数传递给它,在异步Ajax调用完成后将调用最终结果。

这可能是这样的:

function PreSaveAction(callback) { 
    $.ajax({
        url: listUrl,
        type: "GET",
        dataType: "json",
        success: function(data) {
            var retVal = validateUniqueStaff(data);
            // call the callback to report the results of validation
            callback(retVal);
        },
        error: function (data) {
            alert("Error: Problem with the AJAX request");
            callback(false);
        }  
    }); 
}

我在SharePoint PreSaveAction()上进行的一点点搜索表明它必须是同步的。它仅用于客户端验证(没有对服务器的Ajax调用)。要使用它,您必须直接从它返回truefalse,因此您无法在PreSaveAction()实现中使用异步Ajax调用,因为结果将不会在时间。您可能能够使Ajax调用同步(我讨厌因为它可能是糟糕的用户体验),或者您需要找到一种不同的方式来进行服务器辅助验证。

答案 2 :(得分:0)

对于表单验证,自从远古时代以来,在成功验证时从提交处理程序发出form.submit()并无条件地返回false是标准做法。

据推测,在SharePoint环境中,您可以执行相同的操作,但添加了较小的卷积,在这种情况下,只有在成功收到AJAX响应后才会进行验证。

你写的确切取决于validateUniqueStaff返回的内容。

假设validateUniqueStaff返回一个布尔值(有效/无效),你会写:

function PreSaveAction() {
    var form = this;
    //disable Save button here
    $.ajax({
        url: listUrl,
        type: "GET",
        dataType: "json"
    }).then(validateUniqueStaff, function(jqXHR, textStatus, errorThrown) {
        return new Error(textStatus);
    }).then(function(valid) {
        if(valid) {
            form.submit();
        } else {
            return $.Deferred.reject(new Error('Validation failure')).promise();
        }
    }).fail(function(e) {
        alert(e.message);//this will be either the AJAX error message or the validation failure message
    }).always(function() {
        //re-enable Save button here
    });
    return false;
}

或者(从PreSaveAction' s观点来看更优雅),假设validateUniqueStaff返回成功解决的Promise或失败时拒绝的Promise,你会写:

function PreSaveAction() {
    var form = this;
    //disable Save button here
    $.ajax({
        url: listUrl,
        type: "GET",
        dataType: "json"
    }).then(validateUniqueStaff, function(jqXHR, textStatus, errorThrown) {
        return new Error(textStatus);
    }).then(form.submit, function(e) {
        alert(e.message);//this will be either the AJAX error message or the validation failure message
    }).always(function() {
        //re-enable Save button here
    });
    return false;
}

我真的不认为你应该考虑同步AJAX,这是不可靠的,因为它是不必要的。