Асинхронные функции ES7
JavaScript

Асинхронные функции ES7

Оригинал: ES7 async functions, Jake Archibald

Они великолепны. Они великолепны настолько, что я хотел бы изменить закон, чтобы я мог жениться на них.

Асинхронность с обещаниями

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

Код выглядит так:


function loadStory() {
    return getJSON('story.json').then(function(story) {
        addHtmlToPage(story.heading);

        return story.chapterURLs.map(getJSON)
            .reduce(function(chain, chapterPromise) {
                return chain.then(function() {
                    return chapterPromise;
                }).then(function(chapter) {
                    addHtmlToPage(chapter.html);
                });
        }, Promise.resolve());
    }).then(function() {
        addTextToPage("All done");
    }).catch(function(err) {
        addTextToPage("Argh, broken: " + err.message);
    }).then(function() {
        document.querySelector('.spinner').style.display = 'none';
    });
}

Не плохо, но …

То же самое с асинхронными функциями


async function loadStory() {
    try {
        let story = await getJSON('story.json');
        addHtmlToPage(story.heading);
        for (let chapter of story.chapterURLs.map(getJSON)) {
            addHtmlToPage((await chapter).html);
        }
        addTextToPage("All done");
    } catch (err) {
        addTextToPage("Argh, broken: " + err.message);
    }
    document.querySelector('.spinner').style.display = 'none';
}

Асинхронные функции позволяют дождаться обещания. Выполнение функции приостанавливается без блокировки и ждет выполнения обещания. Если обещание выполняется успешно, выполнение асинхронной функции продолжается, если неуспешно — срабатывает блок catch.

Функция loadStory возвращает обещание, поэтому ее можно использовать в другой асинхронной функции:


(async function() {
    await loadStory();
    console.log("Yey, story successfully loaded!");
}());

В ожиданиие ES7...

Использовать асинхронные функции и другие ES6/7 особенности можно уже сегодня с помощью Traceur. Также можно использовать ES6 генераторы, чтобы сделать что-то похожее на асинхронные функции.

Вам понадобится небольшой кусок кода, функция spawn. Теперь вы можете использовать генераторы так же, как асинхронные функции:


function loadStory() {
  return spawn(function* () {
    try {
      let story = yield getJSON('story.json');
      addHtmlToPage(story.heading);
      for (let chapter of story.chapterURLs.map(getJSON)) {
        addHtmlToPage((yield chapter).html));
      }
      addTextToPage("All done");
    } catch (err) {
      addTextToPage("Argh, broken: " + err.message);
    }
    document.querySelector('.spinner').style.display = 'none';
  });
}

В примере выше я передаю в функцию spawn функцию-генератор, вы можете видеть, что это генератор по символу * после function. Функция spawn вызывает метод .next() генератора, получает обещание из вызова yield и ждет его завершения для вызова .next() или .throw().

В ES7 аналог функции spawn является частью спецификации и гораздо проще в использовании. Иметь стандартный способ упростить асинхронное кодирование — это просто фантастика!

Для дальнейшего чтения

Рассылка
Подпишитесь на рассылку и получайте дайджест новостей и статей.
Никакого спама!
Подписаться