在移动到下一行之前无法等待 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在一处。
我很难等待 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在一处。