异步等待 - 等待是否阻止其他代码运行?

Hej*_*123 3 javascript async-await

在javascript中,等待块代码吗?例如,假设我们有以下代码:

async function queryDB() {
    const addUser = await promisePool.execute("INSERT INTO Users (User) VALUES ('username')")
    const selectUser = await promisePool.execute("SELECT User FROM Users") 
}
Run Code Online (Sandbox Code Playgroud)

“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") 
    }
Run Code Online (Sandbox Code Playgroud)

“selectUser”会等待 addUser 而不是 setTimeout 吗?如果是这样,你将如何编写上面的代码让 addUser 先运行,然后 setTimeout 然后 selectUser?

我还想补充一点,我一直在研究和阅读 stackoverflow 和其他资源,但我需要澄清一下。

And*_*eev 6

重要提示:在这里可能是一个坏词。更好的说法是“等待”。更好的办法可能只是说使用await语法完成的操作保证按顺序执行。

大局观

在 Node 中使用异步代码的主要原因是,当我们等待某些异步操作(例如数据库请求、网络请求、文件操作等)时,我们不会阻塞整个应用程序- 我们只阻塞这个特定的执行上下文。

尽管 Node.js 仅使用一个线程来执行用户代码,但 I/O 操作是异步的并且是非阻塞的

因此,假设您有一个带有上面提供的代码的端点,该端点链接到前端的某个按钮“添加用户”。

  • Bill按下按钮,你开始处理请求,开始等待addUser操作
  • 此时约翰也按下了相同的按钮。您的代码仍将被执行,并且还将开始等待直到addUser完成。
  • 假设该Users表已陷入死锁,任何数据库操作都将非常慢,并且我们有第三个用户 Jane,她只是浏览您的网站,但她不需要登录/注册,所以她不接触Users桌子。会发生什么?简一切都很好,她的请求会顺利完成。

如何等待setTimeout

setTimeout来自“上一个时代”,因此它使用回调而不是异步/等待语法。但如果需要,始终可以将回调样式转换为 async/await。

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
await delay(5000);
Run Code Online (Sandbox Code Playgroud)


You*_*saf 5

“selectUser”是否会等到 addUser 完成后才运行,以便我们可以选择添加的用户?

MDN Docs - await:

await 表达式会导致异步函数执行暂停,直到 Promise 被解决(即完成或拒绝),并在完成后恢复异步函数的执行。恢复时, await 表达式的值是已完成的 Promise 的值。

queryDB函数的执行将在等待第一个 promise 完成时暂停。第二行代码只有在第一行成功完成后才会执行。

“selectUser”会等待 addUser 而不是 setTimeout 吗?

对,那是正确的。

如果是这样,你将如何编写上面的代码让 addUser 先运行,然后 setTimeout 然后 selectUser?

您可以包装setTimeout一个返回承诺的函数,然后等待该承诺以确保在前两行完成后执行最后一行。

以下是包装函数的示例 setTimeout

function waitForTimeout(seconds) {
  return new Promise((resolve, reject) => {
     setTimeout(() => { 
        console.log("Hello World");
        resolve();
     }, seconds * 1000);        
  });
}
Run Code Online (Sandbox Code Playgroud)

一旦你有了一个包装函数,你就可以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") 
}
Run Code Online (Sandbox Code Playgroud)