Javascript 为什么';不要懒洋洋地等着街区?

Javascript 为什么';不要懒洋洋地等着街区?,javascript,async-await,Javascript,Async Await,我有兴趣理解为什么使用await立即阻塞,而不是仅在引用awaited值时才延迟阻塞 我希望这是一个启发性的/重要的问题,但我担心这可能被认为超出了本网站的范围-如果是,我会道歉,哭一场,然后把问题带到别处 例如,考虑以下内容: let delayedValue = (value, ms=1000) => { return new Promise(resolve => { setTimeout(() => resolve(val), ms); }); }; (

我有兴趣理解为什么使用
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');
})();
(async() => {

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

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

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

例如,它不同于下面的示例,延迟
console.log显然是不可避免的(因为引用了
wait
ed值):

我发现lazy
await
阻塞有很多好处——它可以导致不相关操作的自动并行化。例如,如果我想阅读两个文件,然后同时使用这两个文件,并且我不是在学习,我会写以下内容:

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

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

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

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

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

让这两个文件并行读取仍然有点混乱,即使在这个美丽的ES7世界中也是如此,因为
wait
会立即阻塞,而不是懒散地阻塞。您需要执行以下操作(当然比上述操作更混乱):

为什么语言设计人员选择让
等待
立即阻止而不是懒惰地阻止?


例如,这会导致调试困难吗?将lazy
await
s集成到javascript中会不会太困难?是否存在我没有想到的情况,懒惰的
wait
s会导致更混乱的代码、更差的性能或其他负面后果?

原因1:JavaScript没有被懒惰地评估。没有检测“何时实际需要某个值”的基础结构

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

让这两个文件并行读取仍然有点混乱

完全不是:

const [file1, file2] = await Promise.all([readFile('file1dir'), readFile('file2dir')]);
您需要执行以下操作


不,您。

如果
await
表达式从未分配给变量,会产生副作用,而这反过来又需要在下一行代码中使用,那么该表达式呢?在这种情况下,lazy
await
是如何工作的?你可以通过使用承诺而不是
await
来完成你所要求的一切。
await
的全部要点是你得到了你不满意的行为。懒散地阻止?这意味着什么?异步操作可能(通常也会)有许多副作用,例如寻址前端数据存储、显示隐藏加载指示器等等,使执行顺序不确定将使使用
Async
成为竞争条件。当然,你可以重新构造你的代码来解决这个问题,但与此同时,你现在也可以重新构造你的代码,而不引入隐藏的竞争条件。啊,我没有想到会有副作用!