Почему не ждет блок лениво? - PullRequest
0 голосов
/ 30 апреля 2018

Мне интересно понять, почему использование 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` ...

});

Это будет ждать, чтобы прочитать 1-й файл, прежде чем начать читать 2-й. Но на самом деле их можно читать параллельно, и 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 немедленно, а не лениво?

например. Может ли это привести к трудностям отладки? Было бы слишком сложно интегрировать lazy await s в javascript? Есть ли ситуации, о которых я не задумывался, когда ленивые await приводят к более сложному коду, снижению производительности или другим негативным последствиям?

1 Ответ

0 голосов
/ 30 апреля 2018

Причина 1: JavaScript не лениво оценивается. Нет инфраструктуры для определения «когда значение действительно необходимо».

Причина 2: неявный параллелизм будет очень трудно контролировать. Что если бы я хотел своих файлов для последовательного чтения, как бы я это написал? Изменение мелочей в синтаксисе не должно приводить к очень разным оценкам.

Получение двух файлов для чтения параллельно все еще немного грязно

Совсем нет:

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

Вам нужно сделать что-то вроде следующего

Нет, вы абсолютно не должны так писать .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...