-
Notifications
You must be signed in to change notification settings - Fork 16
async await
Иногда в нашем коде инициирутся асинхронные операции, результат которых необходим для работы дальнейшего кода
В таком случае необходимо приостановить выполнение кода до завершения асинхронных операций и получения нужных данных
Для этого нужно объявить асинхронную функцию ( с ключевым словом async перед function ),
а в теле функции перед каждым выражением, возвращающим промис, поставить ключевое слово await
Ключевое слово async используется для определения асинхронной функции
Результатом будет объект класса AsyncFunction
async function test () {}
console.dir ( test )▼ async ƒ test()
arguments: (...)
caller: (...)
length: 0
name: "test"
▼ __proto__: AsyncFunction
arguments: (...)
caller: (...)
► constructor: ƒ AsyncFunction()
Symbol(Symbol.toStringTag): "AsyncFunction"
▼ __proto__: ƒ ()
► apply: ƒ apply()
arguments: (...)
► bind: ƒ bind()
► call: ƒ call()
caller: (...)
► constructor: ƒ Function()
length: 0
name: ""
► toString: ƒ toString()
► Symbol(Symbol.hasInstance): ƒ [Symbol.hasInstance]()
► get arguments: ƒ ()
► set arguments: ƒ ()
► get caller: ƒ ()
► set caller: ƒ ()
► __proto__: ObjectПопытка отратиться к объекту AsyncFunction вызовет исключение:
test instanceof AsyncFunctionпоэтому получить ссылку на нее можно, например, так:
var AsyncFunctionConstructor = test.__proto__.constructorили:
var AsyncFunction = ( async function () {} ).__proto__.constructorТеперь исключения не будет:
test instanceof AsyncFunction // trueПоэтому нельзя конструктор объявить как асинхронную функцию - конструктор должен возвращать экземпляр объекта, а не обещание
Ключевое слово await приостанавливает выполнение кода
до завершения асинхронной операции, запущенной выражением, следующим за await
await можно использовать только внутри асинхронных функций
В противном случае будет сгенерировано исключение
⛔️ Uncaught SyntaxError: await is only valid in async functionПредположим, мы загружаем данные с сервера из нескольких JSON-файлов
Эти данные нужны для построения страницы, чем и занимается дальнейший скрипт
В этом случае мы обычно вешаем коллбэки с помощью метода then промисов
Если промисов много, мы выстраиваем цепочку промисов...
В общем, наш код становится громоздким
С помощью асинхронных функций мы синхронизируем асинхронные процессы
Ключевое слово await заставляет код остановится и дождаться, когда следующий за этим словом асинхронный вызов ( промис ) будет завершен с тем или иным результатом
☕ 1️⃣
async function getUsersData () {
var promises = [
fetch ( 'https://api.github.com/users/josh' ).then ( response => response.json() ),
fetch ( 'https://api.github.com/users/heff' ).then ( response => response.json() ),
fetch ( 'https://api.github.com/users/roland' ).then ( response => response.json() )
]
return await Promise.all( promises )
}
getUsersData().then ( users => console.log ( users ) )☕ 2️⃣
async function getUsersData ( userName ) {
var userData = await fetch ( `https://api.github.com/users/${userName}` )
.then ( response => response.json() )
var userRepos = await fetch ( userData.repos_url )
.then ( response => response.json() )
return userRepos
}
getUsersData( 'josh' ).then ( repos => console.log ( repos ) )☕ 3️⃣ Предположим, есть две функции, возвращающие промис:
var getNames = () =>
new Promise ( ( resolve, reject ) => {
setTimeout ( () => { resolve ( "Success" ) }, 1000 )
} )
var getPosts = () =>
new Promise ( ( resolve, reject ) => {
setTimeout ( () => { resolve ( "Success" ) }, 1000 )
} )Каждый вызов длится 1 секунду
Нам нужно получить ответы от этих функций прежде, чем продолжить выполнение кода
Объявим асинхронную функцию:
async function getData () {
console.time ( 'time' )
var posts = await getPosts ().then ( response => response )
var names = await getNames ().then ( response => response )
console.timeEnd ( 'time' )
console.info ( `names: ${ names } | posts: ${ posts }` )
}Функция getData () фиксирует время начала операций ( в секундах )
затем вызовет функцию getPosts () с ключевым словом await,
что означает, что пока асинхронный процесс функции getPosts ()
не завершится тем или иным образом,
выполнение кода будет приостановлено
Итак, getData () ждет завершения асинхронной операции getPosts (),
которая длится 1 сек.
Когда операция будет завершена
( т.е. промис функции getPosts () будет разрешен либо resolve, либо reject ),
функция getData () вызовет функцию getNames (),
опять-таки с ключевым словом await
Опять ожидание ( 1 сек ) завершения асинхронного процесса
функции getNames (), после чего функция getData ()
выведет в консоль суммарную продолжительность всех операций
и полученные результаты
Теперь вызовем функцию getData ()
getData ()и посмотрим в консоль
2 сек. names: Success | posts: SuccessАналогичного результата мы могли достичь с помощью цепочки промисов
Что плохо?
То, что несвязанные между собой асинхронные процессы выстраиваются в очередь
Суммарная продолжительность операций 2 сек
Посмотрим на альтернативный вариант
☕ 4️⃣
function getData ( typ ) {
return new Promise ( function ( resolve, reject ) {
setTimeout ( () => {
console.log ( 'Promise resolved: ', typ )
resolve ( typ )
}, 1000 )
})
}
async function getAllData () {
console.time ( "Total" )
let promises = Array.from ( arguments )
.map ( x => getData ( x ) )
await Promise.all ( promises )
.then ( response => {
console.timeEnd ( "Total" )
console.log ( "response: ", response )
})
}
getAllData ( "figures", "colors", "diameters" )Функция getData () возвращает промис
Промис будет разрешен через 1 сек
Асинхронная функция getAllData ()
формирует массив промисов promises
и запускает сразу все асинхронные процессы
с помощью метода Promise.all ()
Перед вызовом метода Promise.all () стоит ключевое слово await`
Что происходит в этом случае:
Мы не выстраиваем очередь, а запускаем сразу все асинхронные процессы параллельно
Общая продолжительность операции не будет суммой продолжительности всех асинхронных процессов
В нашем примере вместо 3 секунд, которые мы получили бы в случае последовательной обработки запросов ( как в примере 1 ) мы получили общую продолжительность 1 сек
Используем fetch для получения данных трех типов: JSON, text, img
☕ 6️⃣
function getData ( typ ) {
var __data = {
colors: [ "blue", "green", "yellow", "orange", "red" ],
figures: [ "triangle", "circle", "elipse", "square" ],
diameters: [ 100, 200, 150, 250, 300 ]
}
return new Promise ( function ( resolve, reject ) {
setTimeout ( () => {
console.log ( 'Promise resolved: ', typ )
Object.keys ( __data ).indexOf ( typ ) < 0
? reject ( "Data error" )
: resolve ( __data [ typ ] )
}, Math.floor ( 2000 * Math.random() ) )
})
}
async function getAllData () {
let promises = []
for ( var x of arguments ) {
promises.push ( getData ( x ) )
}
return res = await Promise.all ( promises )
}
getAllData ( "figures", "colors", "diameters" )
.then ( response => console.log ( 'response: ', response ) )
© Irina H.Fylyppova 2018
Использование данных материалов или любой их части коммерческими школами ( курсами ) является нарушением авторских прав
| 1 | 2 | 3 | 4 | 5 |
| 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 |
| ⏬ |
|---|
- Блок-схема алгоритма
- Developer Tools
- Chrome DevTools
- Переменные
- Оператор typeof
- Структуры данных
- Операторы присваивания
- Логические выражения
- Условные операторы
- Инкремент
- Свойство length
- Оператор цикла for
- UTF-8
Homework
- Приведение типов
- NaN | null | Infinity
- BigInt (ES10)
- Функции
- Методы
- Методы строк
- Методы массивов
- Date ()
Самостоятельная работа
Практика (XSS)
Homework
- Циклы while и do...while
- Циклы for...of и for...in
- Параметры по умолчанию
- Объект function
Практика
Homework
- Нативные и host-объекты
- Литерал объекта
- Унаследованные свойства
- Конструктор
- Модель наследования
- Публичные и приватные свойства
- Оператор in
1
Homework
- Итерирующие методы массивов
- Тестирование производительности
- SHA
Homework
- Размеры и прокрутка элемента
- Event Loop
- async | await
- API
- REST | HATEOAS
- status codes
JSON placeholder-
JSON server
fake chat
Homework
- strict mode
- Вычисляемые имена свойств
- Краткий синтаксис методов
- Краткий литерал объекта
- Классы
Homework
- :not(:defined)
- Shadow DOM
- Custom elements
- Lifecycle hooks
- whenDefined
- <template>
- slot
1
2
3
Homework
- npm
- webpack
Упражнение 1- ES6 модули
Упражнение 2- --mode | --watch
Упражнение 3
Упражнение 4
Упражнение 5
Упражнение 6
Упражнение 7
Упражнение 8
Homework
| ⏫ |
|---|

Дополнительно
Справочная инфо
Git Bush
TCP/IP
Коды символов