在 javascript 中,await 块代码吗?例如,假设我们有以下代码:
async function queryDB() {
const addUser = await promisePool.execute("INSERT INTO Users (User) VALUES ('username')")
const selectUser = await promisePool.execute("SELECT User FROM Users")
}
“selectUser”是否会等到 addUser 完成后才运行,以便我们可以选择添加的用户?
另外,假设我们在等待之间添加了一些不是承诺的代码,如下所示:
async function queryDB() {
const addUser = await promisePool.execute("INSERT INTO Users (User) VALUES ('username')")
setTimeout(() => console.log('Do something that takes 3 seconds'), 3000);
const selectUser = await promisePool.execute("SELECT User FROM Users")
}
“selectUser”会等待 addUser 而不是 setTimeout 吗?如果是这样,你如何编写上面的代码,让 addUser 先运行,然后 setTimeout 再 selectUser?
我还想补充一点,我一直在研究和阅读 stackoverflow 和其他资源,但我需要澄清一下。
答案 0 :(得分:4)
“selectUser”会等到 addUser 完成后才运行,以便我们可以 选择添加的用户?
<块引用>await 表达式导致异步函数执行暂停,直到 Promise 已解决(即完成或拒绝),并恢复 完成后执行异步函数。复工时, await 表达式的值是已完成的 Promise 的值。
queryDB
函数的执行将在等待第一个 promise 完成时暂停。第二行代码只有在第一行成功完成后才会执行。
“selectUser”会等待 addUser 而不是 setTimeout 吗?
是的,没错。
<块引用>如果是这样,你会怎么写上面的代码让addUser先运行,然后 setTimeout 然后选择User?
您可以将 setTimeout
包装在一个返回承诺的函数中,然后等待该承诺以确保在前两行完成后执行最后一行。
以下是包装setTimeout
的包装函数示例
function waitForTimeout(seconds) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Hello World");
resolve();
}, seconds * 1000);
});
}
一旦你有了一个包装函数,你就可以await
它,如下所示:
async function queryDB() {
const addUser = await promisePool.execute(
"INSERT INTO Users (User) VALUES ('username')"
);
await waitForTimeout(3); // wait for 3 seconds
const selectUser = await promisePool.execute("SELECT User FROM Users")
}
答案 1 :(得分:1)
简短的回答是肯定的,它会阻塞。 await 的目的是确保您在下一行中有可用的结果。因此,如果您需要 addUser 的值来进行下一个查询,您将拥有它。
引入它是为了让您不必在第一行的末尾编写 then() 并将第二个调用放入回调中,这会使代码难以阅读。
答案 2 :(得分:0)
“selectUser”是否会等到 addUser 完成后才运行,以便我们可以选择添加的用户?
是的。
“selectUser”会等待 addUser 而不是 setTimeout 吗?如果是这样,你如何编写上面的代码,让 addUser 先运行,然后 setTimeout 再 selectUser?
"selectUser" 将在 "addUser" 之后执行,但不会在 setTimeout 回调之后执行。如果要在 setTimeout 后运行“selectUser”,可以将其添加到 setTimeout 回调函数中。所以它应该看起来像:
async function queryDB() {
const addUser = await promisePool.execute("INSERT INTO Users (User) VALUES ('username')")
setTimeout(async () => {
const selectUser = await promisePool.execute("SELECT User FROM Users");
}, 3000);
}
答案 3 :(得分:0)
重要说明:块在这里可能是一个坏词。更好的说法是等待。更好的做法可能只是说使用 await
语法完成的操作保证按顺序执行。
大局
在 Node 中使用异步代码的主要原因是我们不会在等待一些异步操作(如数据库请求、网络请求、文件操作等)时阻塞整个应用程序。 - 我们只阻塞这个特定的执行上下文。
尽管 Node.js 只使用一个线程来执行用户代码,但 I/O 操作是异步的并且它们非阻塞。
假设您有一个包含上面提供的代码的端点,该端点链接到前端的某个按钮“添加用户”。
addUser
操作addUser
完成。Users
表陷入死锁,任何使用它的数据库操作都将非常缓慢,我们有第三个用户 Jane,她只是浏览您的网站,但她不需要登录/注册,这样她就不会碰Users
桌子。发生什么了?简完全没问题,她的请求会顺利通过。如何等待 setTimeout
setTimeout
来自“以前的时代”,因此它使用回调而不是 async/await 语法。但是,如果需要,始终可以将回调样式转换为 async/await。
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
await delay(5000);
答案 4 :(得分:0)
简而言之,await 只阻塞当前异步函数中 await 语句之后的代码,而不是整个线程。一旦 await 得到解决,其余的代码就会被执行。在您的示例中,由于您有 2 个 await 语句,因此在第一个完成之前,第二个不会运行,因为第一个阻塞了两个 await 语句所在的函数。对于第二个示例,由于 setTimeout()
不返回承诺并且您也不在等待它,因此该函数会将其视为“同步”操作。也就是说,它会将 setTimeout()
回调抛出到调用堆栈中,直到下一个事件循环并继续执行下一行,这是另一个 await 语句,该语句将再次阻塞该函数,直到它被解析为止。
为了一一执行所有三行,您必须将setTimeout()
放入promise并等待它,以便JS将其视为异步操作并“等待”它在之前完成移至下一行。