Не должен ли асинхронный возврат Promise без явного переноса возвращаемого значения в Promise?

Документация MDN гласит, что

Когда асинхронная функция вызывается, она возвращает Promise. Когда асинхронная функция возвращает значение, Обещание будет разрешено с возвращенным значением. Когда асинхронная функция генерирует исключение или какое-либо значение, Обещание будет отклонено с брошенным значением.

Поэтому что я делаю не так, учитывая что await ожидает решительного обещания?

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
    setTimeout(() => {
        console.log("bar");
        return;
    }, 1000);    
}

function zoo(){
    console.log("zoo");    
}

В соответствии с тем, что я (неправильно) понял, он должен сначала войти bar а потом zoo, но ведёт себя наоборот.

РЕДАКТИРОВАТЬ: Теперь, благодаря разъяснениям от @Matt Morgan, я понимаю ошибку, как bar() функция возвращает undefined, Тем не менее, я думал, что позвонив async сама по себе функция заставит функцию немедленно вернуть нерешенное обещание, и такое обещание будет разрешено, когда async функция будет возвращать любое значение (даже неопределенное). Но теперь я понимаю, что действительно нужно вернуть обещание, объявив его return Promise заявление. Я думаю, что статья MDN для async, о котором я все это читал, немного запутывает эту тему (только мое мнение).

Поэтому я мог бы просто изменить свой bar() функция для:

function bar(){
    return new Promise(function(resolve){
        setTimeout(() => {
            console.log("bar");
            resolve();
        }, 1000);
    });
}

1 ответ

Решение

bar() устанавливает тайм-аут и возвращает значение undefined, что не совпадает с немедленным выполнением оператора регистрации, который запускается по истечении тайм-аута.

Так, zoo() запускается, а затем, когда время ожидания истекает (через 1000 мс), вы видите "бар" в консоли.

Вот модифицированный пример без тайм-аута:

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
   console.log("bar");   
}

function zoo(){
    console.log("zoo");    
}

С нет setTimeout, вы получите порядок исполнения вы ожидаете.

Второй пример, где у вас есть delay() функция, которая оборачивает setTimeout в обещании:

foo();

async function foo(){
    await bar();
    zoo();
}

async function bar(){
   await delay();
   console.log("bar");   
}

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

function zoo(){
    console.log("zoo");    
}

Последний фрагмент кода ожидает разрешения обещания, так что вы видите bar, затем foo,

Выше delay было взято с /questions/31655901/ispolzovanie-settimeout-v-tsepochke-obeschanij/31655924#31655924

Вот последний пример, где bar() возвращает "бар". Это означает, что это завернуто в обещание async декларация, и решается await внутри foo() Опять же, вы видите то, что ожидали увидеть.

foo();

async function foo(){
    console.log(await bar());
    zoo();
}

async function bar(){
    return 'bar';   
}

function zoo(){
    console.log("zoo");    
}

Важно понимать, что ваш оригинальный пример не возвращает значение bar, Возвращается undefined и если вы измените свой исходный код, чтобы выйти возвращенное значение bar() в консоли вы увидите три вещи:

  1. Немедленно возвращенная форма обещания bar() который разрешает undefined,
  2. Значение zoo от zoo() функция.
  3. Наконец, по истечении 1000 мс вы увидите bar вошел из setTimeout это было вытолкнуто в очередь.

Попробуйте, посмотрите, что вы получите.

Другие вопросы по тегам