1

I have the following javascript and JsonResult. The issue I am having is the ajax post doesn't allow enough time for JsonResult to return the appropriate data. I probably don't completely understand javascript processing and I'm sure this is by design but I'm wondering how I can make this a synchronous request. In short, wait for the JsonResult action to complete before the javascript continues processing.

<script type="text/javascript">
$(document).ready(function () {

    var table = document.getElementById("updateTable");
    var tasks = new Array("shutdown", "prep", "boot", "ready");
    var tasksLength = tasks.length;

    for (var i in tasks) {

        for (var loop = 1, max = table.rows.length; loop < max; loop++) {

            id = table.rows[loop].cells[0].innerHTML;
            task = tasks[i];

            ImageUpdateStatus = {
                ImageId: parseInt(id),
                Task: task,
                Status: "pending"
            }

            $.ajax({
                type: "POST",
                url: "UpdateStatus",
                data: $.postify(ImageUpdateStatus),
                success: function (data) {
                    var status = data.status;
                }
            });

            ImageUpdateStatus.Status = status;

            if (ImageUpdateStatus.Status == "success") {

                task = task.concat(" ");

                document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";

                j = parseInt(i) + 1;
                if (j < tasksLength) {
                    nextTask = tasks[j];
                    nextTask = nextTask.concat(" ");
                    document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
                }
            }
        }
    }

    document.getElementById('nextButton').className = "navigation";
    document.getElementById('nextButton').disabled = false;
});

    //
    // GET: /Build/UpdateStatus
    public JsonResult UpdateStatus(ImageUpdateStatus imageUpdateStatus, SessionStateItemCollection sessionItems = null)
    {
        var data = new object();
        string status = null;

        ImageInfo imageInfo = new ImageInfo();
        IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
        imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);

        IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
        IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();

        if (imageUpdateStatus.Task == "shutdown")
        {
            status = svcDevice.Shutdown(imageInfo.ImageId);
            //status = "success";

            data = new
            {
                status
            };
        }

        if (imageUpdateStatus.Task == "prep")
        {
            List<UpdateReasonForm> updateReasonForms;

            if (sessionItems.Keys.Count > 0)
            {
                updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
            }
            else
            {
                updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
            }

            foreach (var item in updateReasonForms)
            {
                if (item.ImageId == imageInfo.ImageId)
                {
                    status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
                }
            }

            data = new
            {
                status
            };
        }

        if (imageUpdateStatus.Task == "boot")
        {
            status = svcDevice.Boot(imageInfo.ImageId);

            data = new
            {
                status
            };
        }

        if (imageUpdateStatus.Task == "ready")
        {
            status = "success";

            data = new
            {
                status
            };
        }

        return this.Json(data, JsonRequestBehavior.AllowGet);
    }

4 Answers 4

3

Just move the code that relies on the result from the ajax request into the success callback function:

$.ajax({
    type: "POST",
    url: "UpdateStatus",
    data: $.postify(ImageUpdateStatus),
    success: function (data) {      
        ImageUpdateStatus.Status = data.status;

        if (ImageUpdateStatus.Status == "success") {

            task = task.concat(" ");

            document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";

            j = parseInt(i) + 1;
            if (j < tasksLength) {
                nextTask = tasks[j];
                nextTask = nextTask.concat(" ");
                document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
            }
        }
    }
});
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome thanks. Do I need to set async: false as well? I have it set now and it seems to be working.
@bcahill No, you don't want async: false as that will lock out the browser until the request is returned.
Setting async: false was the only way I could get it to work. It continued to loop without that set. It works great now though. Thanks.
2

You don't want to make the request synchronous; you want to put all code that depends on the result into your callback:

 $.ajax({
        type: "POST",
        url: "UpdateStatus",
        data: $.postify(ImageUpdateStatus),
        success: function (data) {
            var status = data.status;

            ImageUpdateStatus.Status = status;

            if (ImageUpdateStatus.Status == "success") {
                task = task.concat(" ");
                document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";

                j = parseInt(i) + 1;
                if (j < tasksLength) {
                   nextTask = tasks[j];
                   nextTask = nextTask.concat(" ");
                   document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
                }
            }
        }
    });

Comments

0
$.ajax({
                type: "POST",
                async: false,
                url: "UpdateStatus",
                data: $.postify(ImageUpdateStatus),
                success: function (data) {
                    var status = data.status;
                }
            });

but you really should avoid this, you should really look into making your application work with that wait for the ajax request

1 Comment

Not sure what else I can do to make it wait. Ajax calls a function that shuts down a server, then I ping the server to make sure it is down, and it returns success or failure. Its ignoring async: false unless I do it as explained above.
0

I really feel that you should aggregate any data you need to render your view for the first time on the server side and then push it down to the page. You could use JavaScript to do the rendering once the data is in the page (could be stored in JSON format in a hidden field) but I don't think it's optimal to have the page making an Ajax call when it's rendering for the first time.

1 Comment

The reason for this setup is I have a table of servers. Javascript is taking each item in the row and passing its value to the backend controller. The controller is responsible for shutting down, sending the status of the shutdown back to the page, then prepping the server for updates, sending the status of the prep back to the page, finally boot the server, and send the status of the boot process back to the page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.