【问题标题】:Implementing Callbacks / Deferred Objects with AJAX使用 AJAX 实现回调/延迟对象
【发布时间】:2014-06-19 22:41:19
【问题描述】:

以下是当用户单击表单上的“保存”按钮时调用的函数。当 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 中无效(要求)。

我完全被难住了。任何建议将不胜感激!如果我可以提供任何其他信息,请告诉我。

【问题讨论】:

  • 那么 `validateUniqueStaff` 是什么样的?
  • 您没有在此处展示您在实施 deferred 方面所做的尝试。另一个问题是为什么你甚至需要实现延迟。为什么不让成功回调启动实际的保存操作?或者更确切地说,如果您的验证发生在validateUniqeuStaff 内,则可以调用该保存操作。
  • @adeneo validateUniqueStaff 获取表单上的输入并遍历返回的 JSON 以查找匹配项
  • @MikeBrant 我无法弄清楚如何直接在表单上启动保存操作,这是在 MOSS 2010 中。这会使事情变得更简单。我觉得这至少是一个了解回调的机会。我不期待答案,但任何指导都会有所帮助!
  • @Bread 所以我想问题就在这里:为什么需要返回真/假来表示成功?您似乎想尝试在这里应用程序范例。通常在 js 中,您会看到 AJAX 成功触发 validateUniqueStaff 函数,该函数反过来可能会在成功时调用您的保存函数。在这种情况下,你为什么关心从PreSaveAction() 返回真/假?

标签: javascript jquery ajax callback deferred


【解决方案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;
    }

【讨论】:

    【解决方案2】:

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

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

    如果您的 SharePoint 环境要求 PreSaveAction() 返回 true/false,并且您需要执行 Ajax 操作以确定您应该返回 true 还是 false,那么您就处于绑定状态。您可以使 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 调用同步(我讨厌这可能是一种糟糕的用户体验),或者您需要找到一种不同的方式来进行服务器辅助验证。

    【讨论】:

      【解决方案3】:

      对于表单验证,自古以来的标准做法就是在成功验证时从提交处理程序发出 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 的角度来看更优雅),假设 validateUniqueStaff 返回一个在成功时解决或在失败时被拒绝的 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,它既不可靠又没有必要。

      【讨论】:

      • 顺便说一句,您知道 stackExchange 有一个专门用于 SharePoint 的站点吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多