简体   繁体   中英

Javascript await is only valid in async functions

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

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)

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM