在移动到下一行之前无法等待 javascript 函数调用

Unable to await javascript function call before moving to the next line

我很难等待 javascript 函数,然后再继续下一行代码,这就是控制台中显示的内容。在执行任何其他代码之前,我需要等待该函数。该函数称为 setProjectName,它是从输入元素(类型 = 按钮)的 onclick 中触发的。我需要等待 checkDirectory 函数完成。仅供参考,我曾尝试在 setProjectName 函数中使用 Promise,但没有成功。但是,这可能只是我对 promise 的工作原理了解有限的问题。

以下是我的代码:

async function setProjectName() {
  var projectName = $("#project_name").val();
  var trimName = $.trim(projectName);
  if (!hasWhiteSpace(trimName)) {
    //onError = false;
    if (hasValidCharacters(trimName)) {
      var onError = await checkDirectory(trimName);
      console.log('After checkDirectory: ' + onError);
      if (onError === true) {
        return;
      }
      //onError = false;
      $("#error").text("");
      document.cookie = "ProjectName=" + trimName + "; path=/";
      console.log('after set cookie');
    } else {
      //onError = true;
      $("#error").text("Project name cannot contain special characters!");
    }
  } else {
    //onError = true;
    $("#error").text("Project name cannot contain spaces!");
  }
}

async function checkDirectory(projectName) {
        return new Promise((resolve, reject) => {
            var onError = false;
            $.ajax({
                type: 'GET',
                url: "<%= ConfigurationManager.AppSettings["checkDirUrl"] %>" + "/" + projectName,
                //async: false,
                success: async function (result) {
                    if (result === "folder exists")
                    {
                        //if (confirm('The project name already exists!  Do you wish to delete the project?')) {
                        if (await onConfirm() === 1) {
                            console.log('After deleteDemo');
                            $("#<%= btnHiddenDelete.ClientID %>").click();
                            resolve(1);
                        } else {
                            onError = true;
                            $("#error").text("Project name already exists!");
                        }
                    } else {
                        window.location = ("/Database.aspx");
                    }
                },
                error: function (result) {
                    onError = true;
                    $("#error").text("Error accessing project folder!");
                }
            });
            resolve(0);
        });
    }

async function onConfirm() {
        return new Promise((resolve, reject) => {
            var confirmBox = $("#confirm");
            
            confirmBox.show();
            confirmBox.find($("#yes_btn")).click(function () {
                confirmBox.hide();
                resolve(1);
            });
            confirmBox.find($("#no_btn")).click(function () {
                confirmBox.hide();
                resolve(0);
            });
        });

    }
<input id="continue" class="btn btn-default" type="button" style="margin-left: 10px;" value="Continue" onclick="setProjectName();" disabled>

您的编程模型非常复杂。你混淆了承诺、等待、异步回调、手动创建(和不必要的)承诺、异步等......我的建议是完全切换到 promise-based 设计并使用 built-in 承诺$.ajax() 已经 returns。将 ajax 回调切换为使用 promise resolve/reject.

然后,简化错误处理,以便 checkDirectory() 解决(如果成功)或拒绝(如果有错误)并且 error.message 是您将向用户显示的内容。您目前在 checkDirectory()setProjectName() 中都有错误显示,我认为这确实使设计复杂化。我建议将错误显示全部合并到 setProjectName() 中,这样 checkDirectory() 只是一个实用函数,可以为您提供结果,错误都在 setProjectName().

中处理
// resolves if no error (resolved value is path to redirect to (if not empty))
// rejects if error, e.message in rejection reason is the error message string
async function checkDirectory(projectName) {
    let result;
    try {
        result = await $.ajax({
            type: 'GET',
            url: "<%= ConfigurationManager.AppSettings["checkDirUrl"] %>" + "/" + projectName,
        });
    } catch (e) {
        throw new Error("Error accessing project folder!", { cause: e });
    }
    if (result === "folder exists") {
        if (await deleteDemo() === 1) {
            $("#<%= btnHiddenDelete.ClientID %>").click();
        } else {
            throw new Error("Project name already exists!")
        }
    } else {
        // tell caller to redirect to new page
        return "/Database.aspx";
    }
}

async function setProjectName() {
    try {
        const projectName = $("#project_name").val();
        const trimName = projectName.trim();
        if (hasWhiteSpace(trimName)) {
            throw new Error("Project name cannot contain spaces!");
        }
        if (!hasValidCharacters(trimName)) {
            throw new Error("Project name cannot contain special characters!");
        }
        const redirect = await checkDirectory(trimName);
        if (redirect) {
            window.location = redirect;
            return;
        }
        $("#error").text("");
        document.cookie = "ProjectName=" + trimName + "; path=/";
    } catch (e) {
        console.log(e);
        $("#error").text(e.message);
    }
}

您没有显示 deleteDemo() 的代码,这可能也需要一些修复。

注意,在所有这些代码中,我们在一个地方用一行代码向用户显示错误,因为所有产生错误的地方都只是抛出一个带有自定义消息的错误,然后我们可以捕获所有这些 exceptions/rejections在一处。