javascript - 为什么不等待延迟阻塞?

标签 javascript async-await

我很想知道为什么使用 await 会立即阻塞,而不是仅在引用 awaited 值后才延迟阻塞。

我希望这是一个有启发性/重要的问题,但我担心它可能被认为超出了本网站的范围 - 如果是,我会道歉,哭一会儿,然后把这个问题带到别处。

例如考虑以下几点:

let delayedValue = (value, ms=1000) => {
  return new Promise(resolve => {
    setTimeout(() => resolve(val), ms);
  });
};

(async () => {
  let value = await delayedValue('val');
  console.log('After await');
})();

在立即运行的匿名异步函数中,我们只会看到控制台在延迟后显示 After await。为什么这是必要的?考虑到我们不需要解析 value,为什么语言设计者没有决定在这种情况下立即执行 console.log 语句?

例如,它不像下面的例子,延迟console.log显然是不可避免的(因为引用了awaited值):

(async () => {
  let value = await delayedValue('val');
  console.log('After await: ' + value);
});

我看到延迟 await 阻塞有很多好处——它可以导致不相关操作的自动并行化。例如。如果我想读取两个文件,然后同时处理这两个文件,而且我不够勤奋,我将编写以下内容:

(async() => {

  let file1 = await readFile('file1dir');
  let file2 = await readFile('file2dir');

  // ... do things with `file1` and `file2` ...

});

这将在开始读取第二个文件之前等待读取第一个文件。但实际上它们可以并行读取,并且 javascript 应该能够检测到这一点,因为 file1 直到稍后才被引用。当我第一次学习 async/await 时,我最初的期望是像上面这样的代码会导致并行操作,结果证明是错误的,我有点失望。

让两个文件并行读取仍然有点困惑,即使在这个美丽的 ES7 世界中也是如此,因为 await 立即阻塞而不是延迟阻塞。你需要做类似下面的事情(这肯定比上面的更困惑):

(async() => {

  let [ read1, read2] = [ readFile('file1dir'), readFile('file2dir') ];
  let [ file1, file2 ] = [ await read1, await read2];

  // ... do things with `file1` and `file2` ...

});

为什么语言设计者选择让 await 立即阻塞而不是延迟阻塞?

例如它会导致调试困难吗?将惰性 await 集成到 javascript 中会不会太难了?有没有我没有想到的情况,懒惰的 await 会导致代码更困惑、性能更差或其他负面后果?

最佳答案

原因 1:JavaScript 不是惰性求值的。没有基础架构可以检测“何时真正需要某个值”。

原因 2:隐式并行将很难控制。如果我希望按顺序读取我的文件,我该如何编写呢?更改语法中的小东西不应导致非常不同的评估。

Getting the two files to read in parallel is STILL a bit messy

完全没有:

const [file1, file2] = await Promise.all([readFile('file1dir'), readFile('file2dir')]);

You need to do something like the following

不,你absolutely shouldn't write it like that .

关于javascript - 为什么不等待延迟阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50103855/

相关文章:

javascript - 我正在尝试使用 javascript 将图像添加到 HTML 但没有内容?

javascript - Jasmine单元测试window.onbeforeunload

javascript - 使用 ObjLoader three.js 后如何计算边界框

javascript - Nodejs 代理脚本,不适用于 mod_deflate

c# - 寻找指导以了解如何使用Async和Await进行异步编程

.net - 如何获取异步方法的返回值?

javascript - 摩卡 - TypeError : Cannot read property '$scope' of undefined

c# - 使用 WaitOne(100) 与 WaitOne(0) + Task.Delay(100) 等待命名信号量

javascript - 如何检查 Node js应用程序中请求url参数是否不为空?

angular - 在另一个 promise 中立即更新该值后,将 from 运算符与 promise 一起使用时,Observable 获得错误的值