在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完成后才运行,以便我们选择添加的用户?**
另外,假设我们在waits之间添加一些不是promise的代码,类似这样:
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和其他资源,但我需要一些澄清。
6条答案
按热度按时间8tntrjer1#
“selectUser”是否会等到addUser完成后才运行,以便我们可以选择添加的用户?
从
MDN Docs - await:
await表达式导致async函数执行暂停,直到Promise被解决(即,实现或拒绝),并在实现后恢复async函数的执行。当恢复时,await表达式的值是已实现的Promise的值。
queryDB
函数的执行将暂停,等待第一个promise解决。第二行代码只有在第一行代码成功完成后才会执行。“selectUser”是否会等待addUser而不是setTimeout?
是的,没错。
如果是这样的话,您将如何编写上面的代码,使addUser首先运行,然后setTimeout,然后selectUser?
您可以将
setTimeout
Package 在一个返回promise的函数中,然后等待该promise以确保在前两行完成后执行最后一行。下面是 Package
setTimeout
的 Package 器函数的示例一旦你有了一个 Package 器函数,你可以
await
它,如下所示:zz2j4svz2#
重要提示:* * blocks**在这里可能是一个不好的词。更好的说法是等待。甚至更好的可能是说,使用
await
语法完成的操作可以保证按顺序执行。在Node中使用异步代码的主要原因是我们不会在等待一些异步操作(如数据库请求,网络请求,文件操作等)时阻止整个应用程序。- 我们只阻止这个特定的执行上下文。
尽管Node.js只使用一个线程来执行用户代码,但I/O操作是异步的,并且它们是非阻塞的。
因此,假设您有一个端点,上面展示的代码链接到前端的某个按钮“Add user”。
addUser
操作addUser
完成。Users
表陷入了死锁,任何数据库操作都会非常慢,我们有第三个用户Jane,她只是浏览您的网站,但她不需要登录/注册,所以她不碰Users
表。发生了什么?简很好,她的要求会毫无问题地通过。setTimeout
来自“以前的时代”,所以它使用回调而不是异步/等待语法。但是如果你需要的话,总是可以将回调风格转换为async/await。k10s72fa3#
简而言之,await只阻塞当前异步函数中await语句之后的代码,而不是整个线程。一旦await被解决,剩下的代码就会被执行。在你的例子中,因为你有两个await语句,第二个语句在第一个语句完成之前不会运行,因为第一个语句阻塞了两个await语句所在的函数。对于第二个例子,由于
setTimeout()
没有返回promise,并且您也没有等待它,因此该函数将其视为“同步”操作。也就是说,它会将setTimeout()
回调抛出到调用堆栈中,直到下一个事件循环,并继续执行下一行,这是另一个await语句,它将再次阻塞函数,直到它被解决。为了一个接一个地执行这三行代码,你必须把
setTimeout()
放到一个promise中并等待它,这样JS就把它当作一个异步操作,并在进入下一行之前“等待”它完成。t5fffqht4#
selectUser是否会等到addUser完成后才运行,以便我们选择添加的用户?
是的
selectUser是否会等待addUser而不是setTimeout?如果是这样的话,您将如何编写上面的代码,使addUser首先运行,然后setTimeout,然后selectUser?
“selectUser”将在“addUser”之后执行,但不是setTimeout回调。如果你想在setTimeout之后运行“selectUser”,你可以在setTimeout回调函数中添加它。所以它应该看起来像:
qmb5sa225#
简短的回答是肯定的,它会阻塞。await的目的是确保下一行中有可用的结果。因此,如果您需要addUser的值来进行下一个查询,您将拥有它。
它的引入是为了让你不必在第一行的末尾写then(),并将第二个调用放入回调中,这会使代码难以阅读。
niwlg2el6#
然后EventLoop检查JS调用堆栈是否为空/没有要执行的内容。然后它从MicroTask Queue中获取 addUser 并最终解决。
当这一切发生时,queryDB 被阻塞,因为使用了async await。
然后JS执行 setTimeout,并将回调附加到计时器(浏览器Web API)。
然后JS移动到 selectUser,因为它返回一个promise,所以它被添加到MicroTask Queue。
EventLoop再次检查JS调用堆栈是否为空或/没有要执行的内容。然后,它从MicroTask Queue中获取 selectUser,即使有一个计时器已经过期,并且 setTimeout 的回调函数在回调Queue中。因为微任务队列的优先级>回调队列。
为了避免这种情况,我们需要在JS中使用Promisification。使用 setTimeout 将其 Package 为Promise。以便在添加 selectUser 之前将其添加到微任务队列。
希望能帮上忙!