Home > Software design >  Javascript await is only valid in async functions
Javascript await is only valid in async functions

Time:08-22

I have this function to delete items once a popup returns true:

function deleteItems(selectedItems){
    if (selectedItems.length > 0) {
        $("#confirm-popup-modal").modal("show");
        $("#confirm-popup-modal").one('hidden.bs.modal', function (event) {
            if ($("#confirm-modal").val() == "true") {
                var form_data = selectedItems;
                $.ajax({
                    url: "@Url.Action("Delete", @ViewContext.RouteData.Values["controller"].ToString())",
                    method: "POST",
                    data: JSON.stringify(form_data),
                    contentType: "application/json",
                    success: function (result) {
                        if (result.Result == true) {
                            var deleteId = result.Output;
                            await CompletedJobsAccess(deleteId);
                            table.draw();
                        }
                    },
                    error: function (error) {
                        console.log(error);
                    }
                });
            }
        });
    }
}

Inside the Ajax success is another function called CompletedJobsAccess that will keep looping every 3 seconds to check if a job deletion has been completed:

function CompletedJobsAccess(DeleteId){
    return new Promise((resolve,reject)=>{
        var loopInterval = setInterval(function() { 
            $.ajax({
                url: "@Url.Action("Verify", "CompletedJobsAccess", new {area="Base" })",
                method: "POST",
                data: JSON.stringify(DeleteId),
                contentType: "application/json",
                success: function(verifyResult) {
                    if (verifyResult.IS_COMPLETED == true && verifyResult.IS_PROCESSING == false) {
                        if (verifyResult.IS_SUCCESSFUL == true) {
                            console.log(verifyResult.OUTPUT);
                            $.each($.parseJSON(verifyResult.OUTPUT), function(index, value) {
                                if (value.Result == true) {
                                    toastr.success(value.Message);
                                }else{
                                    toastr.error(value.Message);
                                }
                            });
                            clearInterval(loopInterval);
                        } else {
                            toastr.error(verifyResult.ERROR_MESSAGE);
                        }
                    }
                },
                error: function(innerError) {
                    console.log(innerError);
                }
            });
        }, 3000);
    });
}

However, when I load the page, and call deleteItems(selected);, this is the error I get:

Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules

I tried searching around but I can't find if it can work within an ajax success function.

EDIT:

Added async to the ajax success function but the table draw function doesn't run.

function deleteItems(selectedItems){
    if (selectedItems.length > 0) {
        $("#confirm-popup-modal").modal("show");
        $("#confirm-popup-modal").one('hidden.bs.modal', function (event) {
            if ($("#confirm-modal").val() == "true") {
                var form_data = selectedItems;
                $.ajax({
                    url: "@Url.Action("Delete", @ViewContext.RouteData.Values["controller"].ToString())",
                    method: "POST",
                    data: JSON.stringify(form_data),
                    contentType: "application/json",
                    success: async function (result) {
                        if (result.Result == true) {
                            var deleteId = result.Output;
                            console.log("table before");
                            await CompletedJobsAccess(deleteId);
                            console.log("table draw");
                            table.draw();
                        }
                        table.draw();
                    },
                    error: function (error) {
                        console.log(error);
                    }
                });
            }
        });
    }
}

EDIT 2: Updated CompletedJobsAccess to resolve promises:

function CompletedJobsAccess(DeleteId){
    return new Promise((resolve,reject)=>{
        var loopInterval = setInterval(function() { 
            $.ajax({
                url: "@Url.Action("Verify", "CompletedJobsAccess", new {area="Base" })",
                method: "POST",
                data: JSON.stringify(DeleteId),
                contentType: "application/json",
                success: function(verifyResult) {
                    if (verifyResult.IS_COMPLETED == true && verifyResult.IS_PROCESSING == false) {
                        if (verifyResult.IS_SUCCESSFUL == true) {
                            console.log(verifyResult.OUTPUT);
                            $.each($.parseJSON(verifyResult.OUTPUT), function(index, value) {
                                if (value.Result == true) {
                                    toastr.success(value.Message);
                                }else{
                                    toastr.error(value.Message);
                                }
                            });
                            clearInterval(loopInterval);
                            return Promise.resolve();
                        } else {
                            toastr.error(verifyResult.ERROR_MESSAGE);
                            return Promise.resolve();
                        }
                    }
                },
                error: function(innerError) {
                    console.log(innerError);
                }
            });
        }, 3000);
    });
}

CodePudding user response:

Just make the success function async

$.ajax({
  url: "https://jsonplaceholder.typicode.com/users/3",
  method: "GET",
  success: async function(data) {
    console.log("first - now wait a second ...");
    await new Promise((res) => setTimeout(res, 1000));
    console.log("second, data:",data);
  },
  error: function(innerError) {
    console.log(innerError);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Working JSFiddle (can't work on this site because of CORS)

CodePudding user response:

In CompletedJobsAccess(DeleteId) you return a promise. But the way you set it up it will never execute the resolve function. So your await will wait forever ...

You could place the line

resolve();

right after

clearInterval(loopInterval);

in your CompletedJobsAccess function to make it work.

Do not return yet another Promise.resolve() like you did in your edited code.

A resolve function for a promise is never returned but executed.

CodePudding user response:

Try Adding async before all the function keyword like async function deleteItems(selectedItems){ and also $("#confirm-popup-modal").one('hidden.bs.modal', async function (event) { and it should do the job.

CodePudding user response:

You're using await in functions that don't use the async keyword. await isn't available in regular functions. To solve this, you can change all the functions using await to async function to make it into an asynchronous function.

And if you don't want want to go through every function to make it asynchronous, you can just put the entire code inside an asynchronous IIFE

  • Related