0

I have a function to add a record to database that uses Ajax with C# web service. Prior to updating DB I call another function to validate input that also uses Ajax. So, I need the validate function to finish before continuing with the one adding the record.

I know due to asynchronous nature of ajax I have to use promise/deferred but just can't get my head wrapped around it to set it up properly.

Updated

function validate() {
    var deferred = $.Deferred();
    $.ajax({
        url: "path/to/web/service",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: params,
    }).done(function (result) {debugger
        if (!result || result.d === "") {
            isValid = false;
        }
        else {
            var duplicate = JSON.parse(result.d);
            switch (duplicate) {
                case DuplicateData.Name:
                    isValid = false;
                    break;
                case DuplicateData.ID:
                    isValid = false;
                    break;
            }
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
        alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
    });
    deferred.resolve(isValid);
    return deferred.promise();
    //return isValid;
}

$(document).on("click", "#btnAdd", function (event) {debugger
    $.when(validate())
        .then(function(isValid) {
            if (isValid) {
                $.ajax({
                    url: "path/to/another/webservice",
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    data: some_param,
                }).done(function (result) {
                    addNewRecord();                       
                )}.fail(function (jqXHR, textStatus, errorThrown) {
                    alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
                });
            }
    })
});

function addNewRecord(){
    // add record to DB
}
NoBullMan
  • 2,032
  • 5
  • 40
  • 93
  • Does this answer your question? [How do I chain three asynchronous calls using jQuery promises?](https://stackoverflow.com/questions/16026942/how-do-i-chain-three-asynchronous-calls-using-jquery-promises) – Athanasios Kataras Oct 20 '20 at 05:32
  • I updated the question, incorporating promises, but it still executes the button_add function, then goes to validate function and then to add new record, happily trying to add new record even though validation fails. – NoBullMan Oct 20 '20 at 18:18

1 Answers1

0

As you are only dealing with a boolean result, there is no reason to return a value, you can just resolve or reject the deferred.

function validate() {   
    var $defer = $.Deferred(function() {
        $.ajax({
            url: "path/to/web/service",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: params,
        })
        .done(function (result) {
            // If there's no result
            if (!result || !result.d) {
                $defer.reject();
            }
            else {
                // This call shouldn't be necessary, as dataType: "json" will call it for you
                // Unless you double-encoded it.
                var duplicate = JSON.parse(result.d);
                
                // Not sure about this part, what's DuplicatedData and what does result.d contain? 
                switch (duplicate) {
                    case DuplicateData.Name:
                    case DuplicateData.ID:
                        $defer.reject();
                }
            }
            // Everything checks out, resolve the promise
            $defer.resolve();
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            // If there was a network or server error
            // alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
            $defer.reject();
        });
    });
    return $defer;
}

$('form').on("click", "#btnAdd", function (event) {
    validate()
    .done(function() {
        // If the validation passes
        $.ajax({
            url: "path/to/another/webservice",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: some_param,
        })
        .done(function (result) {
            // Creation successful
            addNewRecord();
        }).fail(function (jqXHR, textStatus, errorThrown) {
            // Creation failed
            alert(textStatus + ' - ' + errorThrown + '\n' + jqXHR.responseText);
        });
    })
    .fail(function(reason) {
        // Called in case of a validation error
        console.log("Validation error");
    });
});
msg
  • 7,863
  • 3
  • 14
  • 33
  • Thank you. Unfortunately, I can't test this in IE because it is too stupid to understand '=>' in function validate() and even more unfortunate is that IE is the standard company browser! – NoBullMan Oct 22 '20 at 00:31
  • @NoBullMan Fortunately, `(resolve, reject) =>` is only a fancy way of writing `function (resolve, reject)`. But IE as "Internet Explorer"? The one that goes up to 11, so to speak? That doesn't even support promises, you'll have to polyfill it... Or go back to using `deferred`, but with no `.promise()`. – msg Oct 22 '20 at 01:15
  • @NoBullMan Ok, I applied the changes but now it's me who cannot test... Hopefully it works. – msg Oct 22 '20 at 01:45
  • Thank you. It's always great when I learn something new from the masters. – NoBullMan Oct 22 '20 at 02:47