Статьи

JavaScript переходит в асинхронный город в краю

С момента появления ранних версий JavaScript прошел долгий путь, и благодаря всем усилиям, предпринятым TC39 (организация, отвечающая за стандартизацию JavaScript ( точнее, ECMAScript )), у нас теперь есть современный язык, который широко используется.

Одна область в ECMAScript, которая получила значительные улучшения — это асинхронный код . Вы можете узнать больше об асинхронном программировании здесь, если вы новый разработчик. К счастью, мы включили эти изменения в новый браузер Edge в Windows 10. Проверьте журнал изменений ниже:

https://dev.modern.ie/platform/changelog/10532-pc/

Среди всех этих новых функций давайте специально сосредоточимся на «Асинхронных функциях ES2016 », стоящих за флагом функций Экспериментального Javascript, и пройдемся по обновлениям и посмотрим, как ECMAScript может улучшить ваш текущий рабочий процесс.

Первая остановка: ECMAScript 5

ECMAScript 5 (и предыдущие версии также) посвящены обратным вызовам. Чтобы лучше это представить, давайте рассмотрим простой пример, который вы наверняка используете чаще, чем раз в день: выполнение XHR-запроса.

var displayDiv = document.getElementById("displayDiv");

// Part 1 - Defining what do we want to do with the result
var processJSON = function (json) {
    var result = JSON.parse(json);

    result.collection.forEach(function(card) {
        var div = document.createElement("div");
        div.innerHTML = card.name + " cost is " + card.price;

        displayDiv.appendChild(div);
    });
}

// Part 2 - Providing a function to display errors
var displayError = function(error) {
    displayDiv.innerHTML = error;
}

// Part 3 - Creating and setting up the XHR object
var xhr = new XMLHttpRequest();

xhr.open('GET', "cards.json");

// Part 4 - Defining callbacks that XHR object will call for us
xhr.onload = function(){
    if (xhr.status === 200) {
        processJSON(xhr.response);
    }
}

xhr.onerror = function() {
    displayError("Unable to load RSS");
}

// Part 5 - Starting the process
xhr.send();

Известные разработчики JavaScript заметят, насколько это знакомо, поскольку обратные вызовы XHR используются постоянно! Это просто и довольно просто: разработчик создает запрос XHR, а затем предоставляет обратный вызов для указанного объекта XHR.

Напротив, сложность обратного вызова происходит от порядка выполнения, который не является линейным из-за внутренней природы асинхронного кода:

образ

« Ад обратного вызова » может быть даже хуже, если использовать другой асинхронный вызов внутри вашего собственного обратного вызова.

Вторая остановка: ECMAScript 6

ECMAScript 6 набирает обороты, и у Edge пока есть лидирующая поддержка с 88% охватом.

Среди множества значительных улучшений ECMAScript 6 стандартизирует использование обещаний (ранее называвшихся фьючерсами).

Согласно MDN , обещание — это объект, который используется для отложенных и асинхронных вычислений. Обещание представляет собой операцию , которая еще не завершена, но , как ожидается , в будущем. Обещания — это способ организации асинхронных операций таким образом, чтобы они выглядели синхронно. Именно то, что нам нужно для нашего примера XHR.

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

Давайте немного обновим наш пример для поддержки обещаний и посмотрим, как он может улучшить читаемость и удобство обслуживания нашего кода:

var displayDiv = document.getElementById("displayDiv");

// Part 1 - Create a function that returns a promise
function getJsonAsync(url) {
    // Promises require two functions: one for success, one for failure
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();

        xhr.open('GET', url);

        xhr.onload = () => {
            if (xhr.status === 200) {
                // We can resolve the promise
                resolve(xhr.response);
            } else {
                // It's a failure, so let's reject the promise
                reject("Unable to load RSS");
            }
        }

        xhr.onerror = () => {
            // It's a failure, so let's reject the promise
            reject("Unable to load RSS");
        };

        xhr.send();
    });
}

// Part 2 - The function returns a promise
// so we can chain with a .then and a .catch
getJsonAsync("cards.json").then(json => {
    var result = JSON.parse(json);

    result.collection.forEach(card => {
        var div = document.createElement("div");
        div.innerHTML = `${card.name} cost is ${card.price}`;

        displayDiv.appendChild(div);
    });
}).catch(error => {
    displayDiv.innerHTML = error;
});

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

Создание обещания

Чтобы «обещать» (извините, но я француз, поэтому мне разрешено придумывать новые слова) старого объекта XHR, вам нужно создать объект Promise :

образ

Используя обещание

После создания обещание можно использовать для цепочки асинхронных вызовов более элегантным способом:

образ

Итак, теперь мы имеем (с точки зрения пользователя):

  • Получить обещание (1)
  • Цепочка с кодом успеха (2 и 3)
  • Цепочка с кодом ошибки (4), как в блоке try / catch

Интересно то, что обещания цепочки легко вызываются с помощью .then (). Then () и т. Д.

Боковой узел. Поскольку JavaScript — современный язык, вы можете заметить, что я также использовал синтаксический сахар из ECMAScript 6, например, строки шаблона или функции стрелок .

Конечная: ECMAScript 7

Наконец-то мы достигли нашей цели! Мы почти в будущем , но благодаря быстрому циклу разработки Edge команда может представить немного ECMAScript 7 с асинхронными функциями в последней сборке!

Асинхронные функции являются синтаксическим сахаром для улучшения модели уровня языка для написания асинхронного кода.

Асинхронные функции построены на основе функций ECMAScript 6, таких как генераторы. Действительно, генераторы могут использоваться совместно с обещаниями для получения тех же результатов, но с гораздо большим количеством пользовательского кода

Нам не нужно менять функцию, которая генерирует обещание, поскольку асинхронные функции работают напрямую с обещанием.

Нам нужно только изменить вызывающую функцию:

// Let's create an async anonymous function
(async function() {
    try {
        // Just have to await the promise!
        var json = await getJsonAsync("cards.json");
        var result = JSON.parse(json);

        result.collection.forEach(card => {
            var div = document.createElement("div");
            div.innerHTML = `${card.name} cost is ${card.price}`;

            displayDiv.appendChild(div);
        });
    } catch (e) {
        displayDiv.innerHTML = e;
    }
})();

Здесь происходит магия. Этот код выглядит как обычный синхронный код с совершенно линейным путем выполнения:

образ

Впечатляет, правда?

И хорошая новость в том, что вы даже можете использовать асинхронные функции с функциями стрелок или методами классов.

Идти дальше

Если вы хотите узнать больше о том, как мы реализовали это в Чакре, ознакомьтесь с официальным постом в блоге Edge: http://blogs.windows.com/msedgedev/2015/09/30/asynchronous-code-gets-easier-with- es2016 Асинхр-функция-поддержка-в-чакре-и-Microsoft-край /

Вы также можете отслеживать ход реализации ECMAScript 6 и 7 в различных браузерах с помощью веб-сайта Kangax : не стесняйтесь также проверить нашу дорожную карту JavaScript !

Пожалуйста, не стесняйтесь оставить нам свой отзыв и поддержать любимые функции, используя кнопку голосования:

образ

Спасибо за чтение, и мы рады услышать ваши отзывы и идеи!