javascript - 为什么不延迟等待阻塞?
问题描述
我有兴趣了解为什么使用await
立即阻塞,而不是仅在await
引用 ed 值后才延迟阻塞。
我希望这是一个有启发性/重要的问题,但我担心它可能被认为超出了本网站的范围 - 如果是,我会道歉,哭一会,然后把这个问题带到别处。
例如,考虑以下内容:
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
显然是不可避免的(因为await
引用了 ed 值):
(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
将lazys集成到javascript中会不会太难了?有没有我没有想到lazyawait
会导致代码更混乱、性能更差或其他负面后果的情况?
解决方案
原因 1:JavaScript 没有被延迟评估。没有基础设施来检测“何时实际需要一个值”。
原因 2:隐式并行将很难控制。如果我希望我的文件被顺序读取,我该怎么写呢?改变语法中的小东西不应该导致非常不同的评估。
让两个文件并行读取仍然有点混乱
一点也不:
const [file1, file2] = await Promise.all([readFile('file1dir'), readFile('file2dir')]);
您需要执行以下操作
不,你绝对不应该那样写。
推荐阅读
- swift - 我想从外部添加一个 UILabel 到我图书馆的收藏视图单元格
- google-cloud-platform - 将 ShareDataset 与 BigQuery 结合使用时是否存在任何性能问题或限制?
- javascript - 在 css 中提交 Eslint 错误时
- java - 在最小化和取消最小化之前无法调整内部框架的大小
- regex - Vim - E488 错误 - 搜索和替换命令中的尾随字符
- ios - Paytm 控制台在 Swift 4 中出现 404 错误
- python - cv2 - 多用户图像显示
- php - 将帐户添加到 suitecrm 时停止重复值
- c++ - 模板类中的 lambda 函数上的 __declspec(noinline) 在 VS2017 中引发语法错误
- google-cloud-platform - apache Beam 中的管道语法是如何实现的?