Await прекрасно работает на асинхронной функции, но не на обещаниях - PullRequest
0 голосов
/ 03 июля 2018

Я играл с async / await и обнаружил странное несоответствие в поведении, в зависимости от того, где вызывается await.

function test(msg) {
  return new Promise(accept => {
    console.log('in promise ', msg);
    setTimeout(() => {
      console.log('in timeout ', msg);
      accept();
    }, 1000)
  });
}

async function run() {
  await test('a');
  await test('b');
}

run();

выводит

in promise  a 
in timeout  a 
in promise  B 
in timeout  B

, что ожидается. Однако, если я переместу await в функцию «test», результат будет изменен очень неожиданным образом:

async function test(msg) {
  const promise = new Promise(accept => {
    console.log('in promise ', msg);
    setTimeout(() => {
      console.log('in timeout ', msg);
      accept();
    }, 1000)
  });
  await promise;
}

function run() {
  test('a');
  test('B');
}

run();

Выходы

in promise  a
in promise  B
in timeout  a
in timeout  B

Может, кто-нибудь объяснит поведение во втором случае? Спасибо.

Ответы [ 5 ]

0 голосов
/ 03 июля 2018

Все await ed Обещания в функции async выполняются (до завершения) последовательно .

В вашем первом сценарии run - это функция async, а ее 2 await вызовы test выполняются последовательно.

Во втором сценарии test - это функция async, и ее одиночная операция await не имеет никакого эффекта (поскольку функция async не имеет второй операции await, которая должна "ждать") .

0 голосов
/ 03 июля 2018

Чтобы ясно увидеть, что происходит, вам нужно поставить еще один console.log('end') в конце кода (после run();):

Для первого примера вывод:

in promise  a
end
in timeout  a
in promise  b
in timeout  b

Для второго примера вывод:

in promise  a
in promise  B
end
in timeout  a
in timeout  B

await приостанавливает выполнение текущей функции до разрешения обещания.

В первом примере test('a') выполняется, но затем run() приостанавливается до тех пор, пока обещание, возвращаемое test('a'), не разрешится, что приведет к выполнению console.log('end').

Во втором примере test('a') выполняется частично, но приостанавливается до разрешения обещания, поэтому затем выполняется test('b'), что также приостанавливается, но затем run() завершается так, console.log('end') может быть выполнено.

Надеюсь, это объяснение поможет!

0 голосов
/ 03 июля 2018

Эти два кодовых блока идентичны:

с ожиданием

await test('a');
test('B');

с цепочкой

test('a')
  .then(() => {
    test('B');
  });

Все, что вы делаете с await, это в ожидании обещания решиться и двигаться дальше. async / await - это просто синтаксический сахар, чтобы избежать всех вложений с несколькими обещаниями

0 голосов
/ 03 июля 2018

Ваша run функция не является асинхронной, поэтому она просто запускает две функции. async / await - это просто альтернативный синтаксис для обещаний, поэтому ваш второй пример эквивалентен следующему:

function test(msg) {
  const promise = new Promise(accept => {
    console.log('in promise ', msg);
    setTimeout(() => {
      console.log('in timeout ', msg);
      accept();
    }, 1000)
  });
  return promise.then(() => undefined);
}

function run() {     
  test('a');
  test('B');
}

run();
0 голосов
/ 03 июля 2018

Когда вы создаете Обещание, тело этого Обещания выполняется немедленно. Вот почему во втором фрагменте кода console.log s внутри new Promise до setTimeout происходят сразу.

Так почему в первом примере это не делает то же самое? Это потому, что второй вызов test не вызывается, пока не завершится первый. Два Обетования по сути связаны между собой, как будто вы написали это:

return test('a').then(() => test('B'));

Если вы сделали это:

const promiseA = test('a');
const promiseB = test('B');
await Promise.all([promiseA, promiseB]);

... вы получите тот же результат, что и второй блок кода.

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