首先我熟悉异步/同步函数的概念。 还有很多和我相关的问题。但我无法在任何地方找到答案。
所以问题是: 有没有办法使用 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'));
获取此函数值的唯一方法是使用 .then
功能。
doStuff('1').then(response => {
console.log(response); // output: mystuffisdone1
doOtherStuffWithMyResponse(response);
// ...
});
现在,我想要的是:
const one = doStuff('1');
console.log(one) // mystuffisdone1
const two = doStuff('2');
console.log(two) // mystuffisdone2
为了解释我自己,我有一个充满回调的异步库。我可以通过使用 Promises 和 async/await 伪装同步行为,将这种异步行为转变为同步行为。 但是还有一个问题,最终还是异步的;在异步函数的范围之外。
doStuff('1').then((r) => {console.log(r)};
console.log('Hello wolrd');
结果将是:Hello world
然后 mystuffisdone1
.这是使用 async/await 函数时的预期行为。但这不是我想要的。
现在我的问题是:有没有办法在没有关键字 async 的情况下做与 await 相同的事情?使代码同步?如果不可能,为什么?
编辑:
谢谢大家的回答,我想我的问题并不是所有人都清楚。为了澄清我的想法,这是我对@Nikita Isaev 回答的评论。
“我理解为什么所有 I/O 操作都是异步完成的;或者并行完成的。但我的问题更多是关于为什么引擎不以异步方式阻止同步函数的调用者这一事实?我的意思是const a = doStuff(...)
是一个 Promise。我们需要调用 .then
来获取这个函数的结果。但是为什么 JavaScript 或 Node 引擎不阻塞调用者(只是调用发生的 block )。如果这是可能的,我们可以做 const a = doStuff(...)
,等待并在 a
中得到结果而不阻塞主线程。正如 async/await 所做的那样,为什么没有 sync/wait 的位置?”
希望现在更清楚了,随时发表评论或提出任何问题:)
编辑 2:
答案的所有精确度都在已接受答案的评论中。
最佳答案
有一些 hacky 方法可以完成所需的操作,但那将是一种反模式。我会尽力解释。回调是javascript中的核心概念之一。当您的代码启动时,您可以设置事件监听器、计时器等。您只需告诉引擎安排一些任务:“当 A 发生时,执行 B”。这就是异步。但是回调很丑陋且难以调试,这就是引入 promises 和 async-await 的原因。重要的是要了解这只是一个语法糖,使用 async-await 时您的代码仍然是异步的。由于 javascript 中没有线程,以同步方式等待某些事件触发或某些复杂操作完成会阻塞整个应用程序。 UI 或服务器将停止响应任何其他用户交互,并继续等待触发单个事件。
真实案例:
例子1.
假设我们有一个网络用户界面。我们有一个按钮,可以在单击时从服务器下载最新信息。想象一下我们同步进行。会发生什么?
myButton.onclick = function () {
const data = loadSomeDataSync(); // 0
useDataSomehow(data);
}
一切都是同步的,代码是扁平的,我们很高兴。但用户不是。
javascript 进程只能在特定时刻执行一行代码。用户将无法点击其他按钮、查看任何动画等,应用程序卡在等待 loadSomeDataSync()
完成。即使持续 3 秒,这也是糟糕的用户体验,您既不能取消也不能看到进度,也不能做其他事情。
例子2.
我们有一个拥有超过 100 万用户的 node.js http 服务器。对于每个用户,我们需要执行一个持续 5 秒的繁重操作并返回结果。我们可以以同步或异步的方式进行。如果我们以异步方式执行会怎样?
- 用户 1 连接
- 我们开始为用户 1 执行繁重的操作
- 用户 2 连接
- 我们返回用户 1 的数据
- 我们开始为用户 2 执行繁重的操作
- …
即我们并行并尽快做所有事情。现在假设我们以同步方式执行繁重的操作。
- 用户 1 连接
- 我们开始为用户 1 执行繁重的操作,其他人都在等待它完成
- 我们返回用户 1 的数据
- 用户 2 连接
- …
现在想象一下繁重的操作需要 5 秒才能完成,并且我们的服务器处于高负载状态,它有超过 100 万用户。最后一个还要等将近500万秒,这肯定不行。
这就是为什么:
- 在浏览器和服务器API中,大部分的输入/输出操作都是异步的
- 开发人员努力使所有繁重的计算异步化,甚至 React 以异步方式呈现。
关于javascript - 有没有办法用 async/await 而不是 Promise 返回一个值?作为一个同步函数做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48046577/