Реализация обратных вызовов / отложенных объектов с помощью AJAX

#javascript #jquery #ajax #callback #deferred

#javascript #jquery #ajax #обратный вызов #отложенный

Вопрос:

Ниже приведена функция, которая вызывается, когда пользователь нажимает кнопку «Сохранить» в форме. Когда функция PreSaveAction вернет true, форма будет отправлена. Если возвращается значение false, ничего не произойдет. Я использую AJAX-вызов here для проверки значений формы и хотел бы, чтобы PreSaveAction возвращал true, если validateUniqueStaff завершается успешно, и наоборот, если это не удается.

 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 (требование).

Я абсолютно в тупике. Любой совет был бы очень признателен! Дайте мне знать, если я могу предоставить какую-либо другую информацию.

Комментарии:

1. И как выглядит `validateUniqueStaff`?

2. Вы не показываете, какую попытку вы предприняли при реализации deferred здесь. Еще один вопрос, который нужно задать, — это зачем вам вообще нужно внедрять deferred. Почему бы просто не выполнить успешный обратный вызов, инициирующий фактическое действие сохранения? Или, скорее, вызовите это действие сохранения изнутри validateUniqeuStaff , если именно там происходит ваша проверка.

3. @adeneo validateUniqueStaff получает входные данные в форме и выполняет итерации по возвращенному JSON для поиска соответствия

4. @MikeBrant Я не смог понять, как инициировать действие сохранения в форме напрямую, это в MOSS 2010. Это значительно упростило бы ситуацию. Я почувствовал, что это была возможность, по крайней мере, узнать об обратных вызовах. Я не ожидаю ответа, но любые рекомендации были бы полезны!

5. @Bread Итак, я думаю, вопрос здесь: зачем вам нужно возвращать true / false, чтобы указать успех? Похоже, вы хотите попытаться применить здесь процедурную парадигму. Часто в js вы увидите, как при успешном выполнении AJAX запускается функция validateUniqueStaff, которая, в свою очередь, может вызывать любую вашу функцию сохранения при успешном выполнении. Почему вас волнует возврат true / false из PreSaveAction() в таком случае?

Ответ №1:

Это действительно возможно!

Вам нужно использовать инструменты разработчика (F12), чтобы получить текущий код Java script за кнопкой.

Вот как действовать дальше:

     //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);
        }  
    }); 
}
  

Небольшой поиск, который я выполнил PreSaveAction() в SharePoint, указывает на то, что он должен быть синхронным. Он был разработан только для проверки на стороне клиента (без вызовов Ajax на сервер). Чтобы использовать его, вам придется возвращать true или false непосредственно из него, и, следовательно, вы не сможете использовать асинхронные вызовы Ajax в своей PreSaveAction() реализации, потому что результат не будет известен вовремя. Возможно, вы сможете сделать свой вызов 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 , что для возврата обещания, которое разрешается при успешном выполнении или отклоняется при сбое, вы бы написали :

 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, который настолько же ненадежен, насколько и не нужен.

Комментарии:

1. Кстати, знаете ли вы, что у StackExchange есть сайт, посвященный SharePoint ?