有没有办法用async / await而不是Promise返回值?作为同步功能

Fol*_*vir 5 javascript asynchronous synchronous

首先,我熟悉异步/同步功能的概念。还有很多与我有关的问题。但是我在任何地方都找不到答案。

所以问题是: 有没有一种方法可以使用async / await返回值而不是Promise?作为同步功能。

例如:

async doStuff(param) {
  return await new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('doStuff after a while.');
      resolve('mystuffisdone'+param);
    }, 2000);
  });
}

console.log(doStuff('1'));
Run Code Online (Sandbox Code Playgroud)

获取此函数值的唯一方法是使用该.then函数。

doStuff('1').then(response => {
  console.log(response); // output: mystuffisdone1
  doOtherStuffWithMyResponse(response);
  // ...
});
Run Code Online (Sandbox Code Playgroud)

现在,我想要的是:

const one = doStuff('1');
console.log(one) // mystuffisdone1
const two = doStuff('2');
console.log(two) // mystuffisdone2
Run Code Online (Sandbox Code Playgroud)

为了说明我自己,我有一个充满回调的异步库。我可以通过使用Promises和async / await来伪造同步行为,从而将该异步行为转换为同步行为。但是仍然存在一个问题,它最终还是异步的。超出异步功能范围。

doStuff('1').then((r) => {console.log(r)};
console.log('Hello wolrd');
Run Code Online (Sandbox Code Playgroud)

结果为:Hello worldthen mystuffisdone1。这是使用异步/等待功能时的预期行为。但这不是我想要的。

现在我的问题是:没有关键字async,有没有办法做与await一样的事情?使代码同步?如果不可能,为什么?

编辑:

谢谢您提供的所有答案,我想我的问题并不是所有问题都显而易见。为了澄清我的想法,这是我对@Nikita Isaev答案的评论。

“我理解为什么所有I / O操作都是异步完成;还是并行完成。但是我的问题更多的是,为什么引擎不以异步方式阻止同步函数的调用者?我的意思const a = doStuff(...)是说Promise我们需要调用.then以获取此函数的结果,但是为什么JavaScript或Node引擎不阻止调用者(仅阻止进行调用的块)。如果可能,我们可以这样做const a = doStuff(...),等待并获得结果a而不阻塞主线程。就像异步/等待一样,为什么没有同步/等待的地方?”

希望现在可以更清楚了,随时发表评论或提出任何问题:)

编辑2:

答案为何的所有精确度都在接受答案的注释中。

Kit*_*aev 4

有一些古怪的方法可以实现所需的目的,但这将是一种反模式。我\xe2\x80\x99会尝试解释一下。回调是 javascript 的核心概念之一。当你的代码启动时,你可以设置事件监听器、计时器等。你只需告诉引擎安排一些任务:\xe2\x80\x9c当A发生时,执行B\xe2\x80\x9d。这就是异步。但回调很丑陋且难以调试,这就是引入 Promise 和 async-await 的原因。重要的是要了解这只是一个语法糖,使用 async-await 时您的代码仍然是异步的。由于 JavaScript 中没有线程,等待某些事件触发或某些复杂操作以同步方式完成会阻塞整个应用程序。UI 或服务器将停止响应任何其他用户交互,并继续等待单个事件触发。

\n\n

真实世界案例:

\n\n

示例 1。

\n\n

让\xe2\x80\x99s 说我们有一个Web UI。我们有一个按钮,单击即可从服务器下载最新信息。想象一下我们同步进行。会发生什么?

\n\n
myButton.onclick = function () {\n  const data = loadSomeDataSync(); // 0\n  useDataSomehow(data);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

一切\xe2\x80\x99s都是同步的,代码很平坦,我们很高兴。但用户不是。

\n\n

JavaScript 进程只能在特定时刻执行一行代码。 用户将无法单击其他按钮、查看任何动画等,应用程序将卡在等待loadSomeDataSync()完成。即使这持续了 3 秒,这也是一个糟糕的用户体验,你既不能取消,也不能看到进度,也不能做其他事情。

\n\n

示例 2.

\n\n

我们有一个 node.js http 服务器,拥有超过 100 万用户。对于每个用户,我们需要执行一个持续 5 秒的繁重操作并返回结果。我们可以通过同步或异步的方式来完成。如果我们异步执行会发生什么?

\n\n
    \n
  1. 用户1连接
  2. \n
  3. 我们开始为用户1执行繁重的操作
  4. \n
  5. 用户2连接
  6. \n
  7. 我们返回用户1的数据
  8. \n
  9. 我们开始为用户2执行繁重的操作
  10. \n
  11. \xe2\x80\xa6
  12. \n
\n\n

也就是说,我们并行尽快地做所有事情。现在想象一下我们以同步方式执行繁重的操作。

\n\n
    \n
  1. 用户1连接
  2. \n
  3. 我们开始为用户 1 执行繁重的操作,其他人都在等待它完成
  4. \n
  5. 我们返回用户1的数据
  6. \n
  7. 用户2连接
  8. \n
  9. \xe2\x80\xa6
  10. \n
\n\n

现在想象一下繁重的操作需要 5 秒才能完成,并且我们的服务器处于高负载状态,它有超过 100 万用户。最后一个要等近500万秒,肯定不行。

\n\n

这\xe2\x80\x99就是为什么:

\n\n
    \n
  1. 在浏览器和服务器API中,大多数i/o操作都是异步的
  2. \n
  3. 开发人员努力使所有繁重的计算异步,甚至 React 也以异步方式渲染。
  4. \n
\n