Як експеримент уявіть наступне: спосіб повідомити середовищу виконання JavaScript призупинити виконання коду за ключовим словом await , коли воно використовується для проміса (promise), і відновити лише один раз (і якщо) promise, який повернула функція, був виконан:
// демо-код. Виключно для експеріментуasyncfunctionfoo() {try {var val =awaitgetMeAPromise();console.log(val); }catch(err) {console.log('Error: ',err.message); }}
Коли проміс завершено, виконання програми продовжується,
якщо він був виконаний вдало, то await поверне значення,
якщо проміс буде відхилено, синхронно буде видано помилку, яку ми зможемо зловити.
Це раптово (і чарівним чином) робить асинхронне програмування таким же простим, як і синхронне. Для цього експерименту необхідні три речі:
Можливість призупинити виконання функції .
Можливість помістити значення всередину функції.
Можливість створити виняток усередині функції.
Це саме те, що нам дозволили генератори! Штучний експеримент насправді реальний , як і реалізація async / await у TypeScript / JavaScript. Під кришкою він просто використовує генератори.
Згенерований JavaScript
Вам не обов’язково це розуміти, але це досить просто, якщо ви читали про генератори . Функцію foo можна просто скласти так:
constfoo=wrapToReturnPromise(function* () {try {var val =yieldgetMeAPromise();console.log(val); }catch(err) {console.log('Error: ',err.message); }});
де wrapToReturnPromise просто виконує функцію генератора, щоб отримати генератор , а потім використовує generator.next(). Якщо значенням є проміс , то він буде мати методи then+catch та, залежно від результату, викликає generator.next(result) або generator.throw (помилка) . Це воно!
Підтримка Async Await у TypeScript
Async - Await підтримується TypeScript since version 1.7. Асинхронні функції мають префікс ключового слова async; await призупиняє виконання, доки не буде повернуто проміс з асинхронної функції, і розгортає значення з повернутого Promise. Він підтримувався лише для target es6 , який перетворюється безпосередньо до ES6 generators.
TypeScript 2.1додано до ES3 and ES5 run-times, тобто ви можете вільно користуватися ним незалежно від середовища, яке ви використовуєте. Важливо зауважити, що ми можемо використовувати async / await з TypeScript 2.1 і багато браузерів підтримують його при глобальном додаванні polyfill for Promise.
Давайте переглянемо цей приклад і цей код, щоб зрозуміти, як працює async / await нотація:
functiondelay(milliseconds:number, count:number):Promise<number> {returnnewPromise<number>(resolve => {setTimeout(() => {resolve(count); }, milliseconds); });}// async function always returns a PromiseasyncfunctiondramaticWelcome():Promise<void> {console.log("Hello");for (let i =0; i <5; i++) {// await is converting Promise<number> into numberconstcount:number=awaitdelay(500, i);console.log(count); }console.log("World!");}dramaticWelcome();
Note: для обох цільових сценаріїв нам потрібно переконатися, що наше середовище виконання має ECMAScript-сумісний с Promise. Цього можно дістатися при вживанні поліфілу для Promise. Нам також потрібно переконатися, що TypeScript знає про існування Promise, встановивши бібліотеку на кшталт "dom", "es2015" or "dom", "es2015.promise", "es5". Ми можемо побачити, які браузери ДІЙСНО мають підтримку Promise (нативну та з використанням поліфілу) тут.