Ожидание синхронной функции синхронно возвращает значение? - PullRequest
0 голосов
/ 02 ноября 2018

Я импортировал функцию из внутренней служебной библиотеки, с которой я не знаком. Для этой библиотеки нет документации, и я просто предположил, что она асинхронная из-за ее имени getUserDetails. Я думал, что это делает запрос http.

Я использовал это в асинхронной функции, подобной этой

async function getAllUserInfo(event) {
    const details = await getUserDetails(event);
    // other stuff
}

Я ошибался в своем предположении. Сотрудник отметил, что это не было асинхронным. Я закончил тем, что изменил это, но когда я использовал это неправильно, это все еще работало. Мне удалось дождаться синхронной функции, и она вернула правильные данные.

Мой вопрос касается того, как это работает. Означает ли предварительное ожидание и ожидание синхронной функции разрешение на следующем тике или же он немедленно возвращается, как и синхронная функция?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Если вы ожидаете значение, которое не является обещанием, оно преобразуется в разрешенное обещание с помощью Promise.resolve.

function sync(){
	return 1
}

(async ()=>{
  const v = await sync(); console.log(v)
})();

(async ()=>{
  const v = await Promise.resolve(sync()); console.log(v)
})()
0 голосов
/ 02 ноября 2018

Это сработало, потому что await не требует, чтобы его операнд был обещанием! Возвращает значение ожидаемого выражения, если это не обещание.

См. документацию для оператора ожидания

Важная часть:

[rv] = await expression; 

expression
    A Promise or any value to wait for.
rv
    Returns the fulfilled value of the promise, or the value itself if it's not a Promise.

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

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

function f() {
  console.log('In f');
}

async function g() {
  console.log('Starting g');
  await f();
  console.log('Finishing g');
}

console.log('Starting the script')
g();
console.log('Finishing the script')

Обратите внимание на вывод сценария:

$ node asynctest.js 
Starting the script
Starting g
In f
Finishing the script
Finishing g

Обратите внимание, как await вызвал "g", который не смог возобновиться, пока не закончился основной блок! Так что await сделал эффект. Если бы вы не поместили ожидание там, то вы бы увидели «Завершение g» перед «Завершение сценария». Попробуйте!

Кстати, причина этого эффекта в том, что даже если await может быть задано выражение, которое не создает обещание, JS превратит операнд без обещания в обещание, немедленно разрешенное до этого значения. Таким образом, обещание все еще создается, и часть после await обрабатывается как обратный вызов, который не может быть выполнен, пока не завершится текущий поток выполнения.

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