Category: JavaScript

22
Янв
2020

JavaScript Async + Await за 5 минут

От автора: скорее всего, вы сталкивались с промисами в своем JavaScript. Они позволяют подключиться к завершению асинхронных вызовов. Они упрощают цепочку асинхронных операций или даже группируют их вместе. Есть один крошечный недостаток. При использовании промисов синтаксис не всегда самый красивый. Представляем async + await. Для тех, кто в лагере TL; DR, async + await являются […]

20
Янв
2020

Вам не нужны циклы в JavaScript

От автора: узнайте, как заменить циклы и использовать функции высшего порядка, такие как map, Reduce и Filter. Почему мы заменяем циклы? Использование функций высшего порядка сделает ваш код: Более читабельный. Понятным. Отлаживаемым. 1. Перебрать все элементы и получить новый модифицированный массив Используя цикл: [crayon-5e2565334501d650681813/] Без цикла: [crayon-5e25653345025247361555/] Примечание: если вы используете map, вы не можете […]

20
Янв
2020

Мигрируем с JavaScript на TypeScript быстро и безболезненно

Хотите воспользоваться преимуществами строго типизированного языка, но боитесь сложной конфигурации? Мы покажем, как легко и быстро ввести TypeScript в ваш проект.

JavaScript – чрезвычайно гибкий и простой в изучении и работе язык. Крупное активное сообщество и масса преимуществ. Однако и подводных камней не меньше. Большинство из них связаны с избыточной свободой программиста. Сегодня мы взглянем на TypeScript – более строгую версию классического JS.

Миграция без изменения сборки

Проще всего отказаться от JavaScript, когда вы начинаете проект с чистого листа: можно не задумываться о совместимости изменений. Но что, если нужно поддерживать и развивать старые программы? Изменение языка разработки кажется плохой идеей, ведь придётся переписать десятки файлов. Долго, скучно, а главное – легко сломать налаженный процесс сборки проекта.

Но TypeScript является надмножеством JavaScript и полностью с ним совместим. Если скормить TS-компилятору JS-код, он не будет возражать. Миграцию на TypeScript можно проводить постепенно, файл за файлом. Писать новые скрипты на TypeScript, а существующие –переписывать в удобном темпе.

Попробуем добавить TypeScript в имеющийся проект, не меняя конфигурации webpack, gulp или другого сборщика, которым вы пользуетесь.

Шаг 1. Устанавливаем и настраиваем TypeScript

Прежде всего нужно установить TypeScript в приложение (или глобально):

            npm install --save-dev typescript 
        

Примечание: в зависимости от проекта вам могут потребоваться также пакеты типов (@types) для различных библиотек. Например, для react-redux нужно установить следующие модули:

            npm install --save-dev @types/node
npm install --save-dev @types/react
npm install --save-dev @types/react-dom
npm install --save-dev @types/react-redux
npm install --save-dev @types/react-router-dom 
        

Теперь добавим в корень проекта файл tsconfig.json. В нём будут содержаться настройки компилятора, необходимые для конвертации. Возьмите для начала предлагаемую ниже конфигурацию. Она обеспечивает полную совместимость JS и TS синтаксисов.

tsconfig.json
            {
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
    "jsx": "react"
  },
  "exclude": [
    "node_modules"
  ]
} 
        

Чтобы настроить конфигурационный файл под нужды вашего проекта, обратитесь к документации TypeScript.

Теперь в секцию scripts файла package.json добавим команду для компиляции:

package.json
            "tsc:w": "tsc -w" 
        

При запуске в терминале все файлы с расширением .ts или .tsx будут транслированы в js-файлы. Утилита разместит их по тому же пути, а значит, сборщик сможет работать как раньше, игнорируя ts-исходники.

Примечание: если в проекте нет ни одного .ts-файла, в консоли появится ошибка. Не пугайтесь, команда работает в режиме наблюдения. Как только вы создадите первый typescript-файл, компиляция заработает правильно.

Результат компиляции TypeScript-файла
            file.ts
├── file.js
└── file.js.map 
        

А теперь пусть начнётся магия 💫. Берём любой JS-файл, и меняем расширение на .ts. Компилятор обрабатывает его без возражений.

Мы только что, не особо напрягаясь, сделали первый шаг для миграции проекта на TypeScript, не внеся ни одного изменения в существующую сборку.

Добавим строгости

Большой прыжок вперёд с технической точки зрения, но в самой разработке ничего не поменялось: ни нового кода, ни преимуществ TypeScript.

Создадим простое приложение, определяющее, может ли пользователь взять ипотечный кредит.

Напишем функцию getSavings, которая будет собирать информацию о доходах и сбережениях клиента:

            function getSavings() {
//returns savings
} 
        

На основании этих данных функция concedeMortgage будет принимать решение о выдаче кредита:

            function concedeMortgage(homeValue) {
    const savings = getSavings();
    return savings / homeValue > 0.2;
} 
        

Чтобы приложение работало нормально, необходимо добавить проверку входных данных. Существует ли значение homeValue, является ли оно числом? Кроме того, нужно убедиться, что функция getSavings() возвращает корректное значение сбережений. Итак, код немного разрастается:

            function concedeMortgage(homeValue) {
    if(!homeValue || !parseFloat(homeValue)) return false;
    const savings = getSavings();
    if(!savings || !parseFloat(savings)) return false;
    return savings / homeValue > 0.2;
} 
        

Это выглядит некрасиво, пора воспользоваться преимуществами TypeScript.

noImplicitAny

Добавьте в файл tsconfig.json в секцию compilerOptions новую опцию:

tsconfig.json
            "noImplicitAny": true 
        

Можно не проверять, являются ли входное значение и результат работы getSavings числами. Мы просто укажем нужный тип. Проверки станут короче:

            function concedeMortgage(homeValue: number): boolean {
  if(!homeValue) return false;
  const savings = getSavings();
  if(!savings) return false;
  return savings / homeValue > 0.2;
} 
        

Теперь можно отловить ошибку типа на стадии компиляции! TypeScript не позволит вызвать функцию concedeMortgage, например, со строковым значением:

            concedeMortgage("foo");
// ERROR! Argument of type 'foo' is not assignable to parameter type 'number' 
        

К сожалению, значения null и undefined всё ещё допустимы в каждом типе, так что можно безнаказанно делать вот так:

            concedeMortgage(null) 
        

Не переживайте, сейчас мы это поправим.

strictNullChecks

Активируйте опцию компилятора:

tsconfig.json
            "strictNullChecks": true 
        

Теперь вызов функции с null также приводит к ошибке. Можно убрать все проверки и вернуть concedeMortgage к первозданному чистому виду:

            function concedeMortgage(homeValue: number): boolean {
  const savings = getSavings();
  return savings / homeValue > 0.2;
} 
        
***

Это была лишь малая часть магии TypeScript. Он способен существенно облегчить работу JavaScript-программиста, не требуя при этом никакой особенной настройки и сложной конфигурации.

А вы уже используете TypeScript в своих проектах?

09
Янв
2020

Тонкое искусство прогностической предварительной выборки

От автора: когда вы заказываете гамбургер с картофелем фри в любом ресторане в Америке, официант часто подносит бутылку кетчупа к столу еще до того, как гамбургер будет готов. Хотя вы, возможно, и не просили явно кетчуп, официант предполагает, что вы попросите об этом, так как большинство американцев едят гамбургеры с кетчупом. Но что, если оптимизация […]

07
Янв
2020

Чего ждать от JavaScript в 2020 году? 7 фич, которые вот-вот попадут в стандарт

Посмотрим, какие предложения по развитию языка добрались до четвертой стадии в процессе TC39. Примеряем новики, сравниваем с текущим состоянием.

Ура-ура! Сразу несколько приятных и полезных фич перешли на стадию завершения, а значит в 2020 году нас ждет много радостей. Наконец-то в стандарте появятся долгожданные опциональные последовательности и динамический импорт. Оставим их на сладкое, а сначала посмотрим, что еще приготовил разработчикам TC39.

Если вы не можете удержаться, загляните в репозиторий пропозалов на страничку Finished Proposals. Там вы найдете полный список предложений, достигших стадии 4.

String.prototype.matchAll

Представим, строка сопоставляется с подстрокой или регулярным выражением. Чтобы найти все совпадения, придется потрудиться. Ведь метод String.prototype.match для обычной регулярки возвращает информацию только о первом совпадении:

            let re = /ll(o|y)/;
let reg = /ll(o|y)/g;
let str = 'Hello Dolly';

str.match(re); 
        
Вызов метода String.prototype.match с обычным регулярным выражением

А для глобального регулярного выражения возвращается малоинформативный массив:

            str.match(reg); 
        
Вызов метода String.prototype.match с глобальным регулярным выражением

В прототипе RegExp есть подходящий метод exec. Для обычного выражения он работает так же, как String.prototype.match – ничего интересного:

            re.exec(str); 
        
Вызов метода RegExp.prototype.exeс для обычного регулярного выражения

С глобальными регулярками уже можно работать:

            reg.exec(str);
reg.exec(str);
reg.exec(str); 
        
Вызов метода RegExp.prototype.exeс для глобального регулярного выражения

Каждый вызов возвращает следующее совпадение, а когда строка кончится – null. Чтобы перебрать длинные строки, можно воспользоваться циклом while. Позиция для начала поиска хранится в свойстве lastIndex объекта регулярного выражения. Это не так уж очевидно, правда?

На смену этому подходу пришел удобный и интуитивно понятный метод String.prototype.matchAll. Он возвращает итератор:

            str.matchAll(re); 
        
Метод String.prototype.matchAll возвращает итератор

Вызов next() выводит каждое следующее значение:

Перебор совпадений с помощью метода next

Но можно воспользоваться уже имеющимися благами ES6 и сделать вот так:

            [...str.matchAll(reg)]; 
        
Деструктуризация итератора

Одной строчкой кода мы собрали полную информацию обо всех совпадениях в строке.

BigInt

До появления нового типа данных BigInt приходилось пользоваться типом Number. Самое большое число, которое можно было точно представить в JavaScript, равнялось 2⁵³-1 (константа Number.MAX_SAFE_INTEGER).

Теперь не обязательно ограничивать себя этой ничтожной величиной. Расправьте крылья и воспарите в пространстве по-настоящему больших чисел.

Чтобы создать значение с типом BigInt, добавьте к числу n или воспользуйтесь встроенной функцией BigInt().

            let bigInt = 4n
console.log(bigInt * bigInt) // 16n 
        
  1. Значение BigInt не может быть строго равно значению Number, но выражение 2n == 2 истинно.
  2. При делении результат всегда будет округляться до нуля (4n / 10n = 0n).
  3. Нельзя смешивать в одной операции BigInt и Number, так как неявное преобразование между этими типами не происходит (4n + 2).

globalThis

Получение доступа к глобальным объектам – это вечная головная боль в JavaScript. В каждой среде выполнения свои особенности, свой синтаксис, который нужно знать, чтобы ваш код можно было свободно портировать.

Обычно мы выходили из этого положения, создавая функцию getGlobal(), внутри которой перебирали все возможные варианты:

            const getGlobal = function() {
  if (typeof self !== 'undefined') { return self; }
  if (typeof window !== 'undefined') { return window; }
  if (typeof global !== 'undefined') { return global; }
  throw new Error('no global object found');
};

const globals = getGlobal(); 
        

После того как появился globalThis, можно с чистой совестью забыть об этом зоопарке. Например, в браузере в объекте globalThis вы найдете знакомый window:

Объект globalThis в браузере равен объекту window

Promise.allSettled

Если вам требуется дождаться выполнения сразу нескольких промисов, вы, конечно, обратитесь к методу Promise.all(). Но он принимает только успешно выполненные «обещания». Если где-то появится ошибка, продолжить работу не получится.

Новому методу Promise.allSettled() наплевать, как завершились ваши промисы – главное, что они отработали.

            const fulfilledPromise = Promise.resolve("success");
const rejectedPromise = Promise.reject("error")
const promises = [fulfilledPromise, rejectedPromise];

Promise.allSettled(promises)
  .then((results) => results.forEach((result) => console.log(result))); 
        

Динамический импорт

Еще одна новая фича JavaScript, которой вы наверняка будете пользоваться – динамический импорт. Теперь модули можно загружать прямо в рантайме – в зависимости от некоторого условия или просто отложенно, чтобы не загружать клиент. Достаточно вызвать функцию import(), передать указатель на нужный модуль, и получить ответный промис.

            import("some_module")
  .then(module => {
    module.doSomething();
  })
  .catch(err => {
    console.error(err.message);
  }); 
        

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

            import(`${some_module}.js`)
  .then(module => {
    module.doSomething();
  })
  .catch(err => {
    console.error(err.message);
  }); 
        

Nullish coalescing

У вас есть некоторый объект. Нужно получить и вернуть значение одного из его свойств, если оно не равно null или undefined. В обратном случае возвратить значение по умолчанию. Как бы вы решили эту задачу?

Наверняка вы обратитесь к логическому оператору ИЛИ (||):

            const response = someResponse.properties.mayBeUndefined || 'Response'; 
        

Но есть небольшая проблема. Если в свойстве лежит пустая строка или ноль, мы все равно получим в ответе правую часть выражения ('Response'), так как это ложные значения:

            const someResponse = {properties: { mayBeUndefined: ''}}
const response = someResponse.properties.mayBeUndefined || 'Response';
console.log(response); // Response 
        

Оператор Nullish coalescing, или оператор объединения с null, позволяет решить эту задачу. Если свойство равно null или undefined, то вернется правое значение. Во всех остальных случаях – левое. Независимо от того, истинное оно или ложное.

            const someResponse = {properties: { mayBeUndefined: ''}}
const response = someResponse.properties.mayBeUndefined ?? 'Response';
console.log(response); // '' – пустая строка 
        

Опциональные последовательности

Если вы хоть раз пытались получить глубоко вложенное свойство объекта, то знаете, какая это мука. На каждом уровне поджидает ошибка – ведь искомого свойства может и не быть. Приходится действовать пошагово, доставать всю цепочку свойств по очереди, одно за другим. Это ужасно утомляет и нервирует.

            const someObj = {
  property: 'prop',
  otherProperty: {
    name: 'prop2'
  }
};
const property = someObj.NotOtherProperty ? someObj.NotOtherProperty.name: undefined;
console.log(property); // undefined 
        

Нас спасут опциональные последовательности (англ. Optional Chaining). Достаточно поставить рядом с потенциально несуществующим свойством оператор ?. (вопросительный знак как символ сомнения и точка для стандартного доступа к свойству объекта).

            const someObj = {
  property: 'prop',
  otherProperty: {
    name: 'prop2'
  }
};
const property = someObj.NotOtherProperty?.name;
console.log(property); // undefined 
        

Результат тот же, а запись короче и понятнее!

Вы тоже не можете дождаться?

Если у вас чешутся руки использовать эти приятные возможности в работе, не ограничивайте себя! Многие из них уже воплощены в движках и практически для всех есть плагины babel. Наслаждайтесь 😉

Какая из новых фич JavaScript вам нравится больше всего?

26
Дек
2019

Прекрасный опыт прокрутки — без библиотек

От автора: одной из областей, где Интернет традиционно отстает от нативных платформ, является воспринимаемая «привлекательность» приложения. Частично это восприятие происходит от того, как пользовательский интерфейс реагирует на взаимодействие с пользователем, включая прокрутку содержимого. Столкнувшись с ограничениями веб-платформы, разработчики часто обращаются к библиотекам и фреймворкам JavaScript, чтобы изменить процесс прокрутки веб-страницы — иногда называемый “scroll-jacking” — […]

20
Дек
2019

19 ноября 2019 – 2 марта 2020, Гусев: III Всероссийский конкурс «Программируй будущее»

Студентов технических специальностей зовут создавать сервисы для цифрового ТВ на базе StingrayTV на JavaScript. Лучшие получат до 300 000 рублей.
— Читать дальше «III Всероссийский конкурс «Программируй будущее»»

09
Дек
2019

Используйте модули для создания модульного приложения JavaScript

От автора: одна из главных особенностей ES6 — поддержка JavaScript встроенных модулей. Модули позволяют совместно использовать код различными файлами, используя синтаксис export и import. Это значительное улучшение по сравнению с использованием тегов script и глобальных переменных для совместного использования кода. Использование тегов script было сопряжено с ошибкам, так как порядок загрузки имеет значение. Указание script […]

07
Дек
2019

Redux и Vuex: правая и левая палочки Twix

Абсолютно разные создатели, совершенно разные фабрики и такие разные библиотеки для управления состоянием. Попробуй обе и реши – на чьей стороне ты?

Redux и Vuex – это две совершенно разные библиотеки или одно и то же в разной обертке? Пора разобраться в этой загадке. Начнем с начала – с понимания задачи, которую они пытаются решить.

Управление состоянием

И в документации Redux и в документации Vuex можно найти очень похожие друг на друга фрагменты, объясняющие, зачем вам нужен один или второй инструмент. Идея сводится к тому, что чем сильнее разрастается ваш проект, тем сложнее контролировать поток данных в нем.

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

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

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

Каждый компонент приложения взаимодействует напрямую с хранилищем состояния

Чем ветвистее дерево компонентов, тем очевиднее преимущества такой схемы. Если что-то идет не так, вы всегда знаете, где искать проблему. Такие проекты легко тестировать и расширять, так как разные компоненты мало зависят друг от друга.

Одна цель

Redux и Vuex созданы для решения одной и той же задачи – управления состоянием большого приложения. Возможно, они делают это принципиально разными способами, давайте посмотрим.

Хранилище состояния

И в Redux, и во Vuex данные приложения хранятся в виде обычного объекта. На самом деле, в JavaScript довольно сложно придумать другой способ, так что особого выбора у них не было.

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

Redux

Создадим хранилище Redux:

            const store = new Store(reducers, initialState); 
        

В reducers передается набор обработчиков, изменяющих данные. Как именно происходит этот процесс, мы увидим чуть позже. initialState – это исходные данные, которые нужно положить в хранилище в самом начале работы.

У хранилища в Redux есть несколько полезных методов:

  • getState() – получение актуального состояния;
  • dispatch() – вызов действия для изменения состояния;
  • subscribe() – подписка на изменения.
Хранилище в Redux и его взаимодействие с компонентами

Vuex

А вот так создается хранилище во Vuex:

            new Vuex.Store({
  state: {},
  getters: {},
  mutations: {},
  actions: {},
}); 
        

Сами данные хранятся в объекте state. getters, как вы, вероятно, догадались, будет содержать геттеры для получения информации. С mutations и actions разберемся чуть позже, сейчас достаточно понимать, что их основное предназначение – изменять данные в хранилище.

Одна идея

Между хранилищами в Redux и Vuex нет принципиальной разницы, но есть организационная. Объект с данными прячется внутри некоторого Store и его изменение осуществляется только опосредованно – через мутации (Vuex) или действия (React). Это позволяет защитить данные от неконтролируемых прямых изменений.

Перейдем к реализации взаимодействия компонентов с хранилищем.

Получение данных

В реальном проекте важно не только получить данные, но и узнать, если они изменятся. Как справляются с этим наши испытуемые?

Redux

Redux обзавелся специальным методом getState(), который возвращает все состояние приложения разом.

            <HelloWorld text={store.getState().text} /> 
        

Для отслеживания изменений данных и реакции на них обычно используется какая-нибудь дополнительная система UI-биндинга, например, библиотека react-redux (при использовании Redux в React-приложениях). Но при желании вы можете напрямую подписаться на обновления состояния с помощью метода subscribe.

            store.subscribe(() => console.log(store.getState())) 
        

Vuex

Во Vuex вы можете обратиться к свойствам напрямую, достав их из store.state:

            computed: {
  count() {
    return this.$store.state.count;
  }
} 
        

Но создатели решили не останавливаться на этом и завели геттеры – вычисляемые свойства хранилища, в которые можно поместить более сложную логику:

Пример из документации:

            // определяем геттер при создании хранилища

const store = new Vuex.Store({
  state: {
    todos: [ ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done);
    }
  }
});

// затем обращаемся к нему в компоненте

computed: {
  doneTodosCount () {
    return this.$store.getters.doneTodosCount
  }
} 
        

Во Vuex есть еще несколько плюшек, облегчающих труд разработчика (вроде mapState), но они не вносят радикальных перемен в концепцию.

Что касается отслеживания изменений данных, вы можете полностью положиться на Vuex. Хранилище реактивно, поэтому компоненты, полагающиеся на его состояние, будут автоматически обновляться при необходимости.

Разные методы

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

Изменение данных

Переходим к самому интересному – изменению данных в хранилище. Это ключевой момент, влияющий на все приложение. Здесь важно сохранить новые данные, не потеряв при этом все остальное.

Redux

В основе философии Redux лежит понятие иммутабельности (неизменяемости). Нельзя изменить объект с данными, можно только заменить его целиком. Никаких сайд-эффектов, никаких неприятных сюрпризов – только чистый функциональный подход.

В Redux есть лишь один законный способ изменить состояние приложения – совершить действие (actions).

Экшн – это самый обычный объект, который описывает происходящее изменение. Например, он может выглядеть вот так:

            let action = {
  type: 'ADD_USER',
  user: {name: 'Dan'}
}; 
        

Поле type – обязательное, оно содержит тип действия. Все остальное зависит только от вас.

Теперь это действие нужно передать в хранилище с помощью метода dispatch:

            store.dispatch(action);
 
        

Как именно это действие изменит существующее состояние? Для этого предназначены редьюсеры (reducers), о которых мы уже говорили. Это обычные функции, которые получают на вход старое состояние и действие (экшн), а возвращают новое состояние.

            const someReducer = function(state, action) {
  ...
  return newState;
} 
        

Все очень просто:

  1. Какой-нибудь компонент хочет изменить состояние и диспатчит соответствующий экшн.
  2. Оно прогоняется через редьюсеры, которые анализируют тип действия и вносят необходимые изменения.
  3. Возвращенный цепочкой редьюсеров объект становится новым состоянием приложения.

Философия Redux требует, чтобы редьюсеры соответствовали концепции чистых функций (pure functions), то есть не имели никаких побочных эффектов и не зависели от внешних условий.

Vuex

Во Vuex тоже всего один законный способ изменять состояние – мутации (mutations).

Каждая мутация имеет собственное название и соответствующую ей функцию-обработчик. Все мутации описываются при инициализации хранилища.

            const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state, count) {
      state.count += count
    }
  }
}); 
        

Первым параметром передается текущее состояние, вторым – дополнительные данные мутации (нагрузка). Внутри мутации мы просто обращаемся к свойству state.count напрямую.

Вызов мутации во Vuex очень похож на вызов экшна в Redux:

            store.commit('increment', 10); 
        

Каждая мутация состояния отслеживается и реактивно передается компонентам.

Разные понятия

На первый взгляд, подходы Vuex и Redux к изменению состояния принципиально отличаются. Редьюсеры и иммутабельность данных против мутаций. Разные концепции, разные понятия, но суть для разработчика одна: не лезь в данные напрямую, используй только разрешенные методы изменения.

Redux несколько серьезнее относится к отсутствию сайд-эффектов, Vuex предоставляет несколько более интуитивный интерфейс.

Асинхронное изменение данных

Асинхронность – одна из основных концепций JavaScript в целом. Асинхронных действий в вебе не меньше (а может и больше), чем синхронных. Представим простую асинхронную задачу.

Есть компонент-кнопка, при нажатии на которую отправляется запрос на сервер. Пока не получен ответ, нужно вывести прелоадер, чтобы пользователь знал, что что-то происходит. Затем нужно отобразить полученные данные (например, вывести табличку) или показать ошибку, если запрос завершился неудачно.

Redux

В Redux нет асинхронной функциональности из коробки.

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

Vuex

Мутации в Vuex тоже являются синхронными, внутри них нельзя отправлять запросы к серверу. Но у библиотеки тут есть козырь в рукаве – действия (не путать с действиями в Redux).

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

            const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++;
    }
  },
  actions: {
    increment(context) {
      context.commit('increment');
    }
  }
}); 
        

Вызвать такое действие не сложнее, чем запустить мутацию:

            store.dispatch('increment'); 
        

Внутрь действия может быть помещена любая асинхронная логика.

Документация советует избегать запуска мутаций напрямую, а вызывать их только внутри действий.

Обратите внимание: действия являются лишь оберткой над мутациями – единственным законным способом изменения состояния.

Разные возможности

Что ж, тут Vuex из коробки обошел Redux, создав собственную (и весьма простую!) асинхронную функциональность.

Правая и левая палочки Twix

Redux и Vuex – это две палочки Twix. Они производятся на разных фабриках и по уникальным технологиям, но в итоге мы имеем очень похожие продукты.

На палочку Redux карамель льется волнами, а на палочку Vuex – струится:

  • Redux многословнее и строго придерживается принципов функционального программирования.
  • Vuex понятнее для изучения и проще при разработке.

На палочку Redux шоколад наливается вертикально, а на палочку Vuex – сверху вниз:

  • Redux не привязан к конкретному фреймворку и может работать где угодно, но требует дополнительных зависимостей.
  • Vuex прочно связан с Vue и имеет много плюшек от тесной интеграции.

А чему отдаете предпочтение вы?

29
Ноя
2019

Что такое super() в JavaScript?

От автора: что происходит, когда вы видите некоторый JavaScript, который вызывает super()? В дочернем классе вы используете super() для вызова конструктора его родителя и super.&ltmethodName> для доступа к методам его родителя. Эта статья предполагает хотя бы небольшое знакомство с понятиями конструкторов и дочерних и родительских классов. Super не уникален для Javascript — многие языки программирования, […]

28
Ноя
2019

Готовящиеся к выпуску новые функции JavaScript

От автора: после релиза ECMAScript2015 (также называемого ES6) JavaScript изменился и улучшился. Это отличная новость для всех разработчиков JavaScript. Кроме того, новая версия ECMAScript выпускается каждый год. Скорее всего, вы не заметили, какие функции были добавлены в последнюю версию ECMAScript, выпущенную в июне 2019 года. Я кратко расскажу вам о новых функциях, добавленных в последней […]

19
Ноя
2019

Написание асинхронных задач в современном JavaScript

От автора: в этой статье мы исследуем эволюцию JavaScript в аспекте асинхронного выполнения от прошлой эпохи и до того, как он изменил способ написания и чтения кода. Мы начнем с начала веб-разработки и пройдем весь путь до современных примеров асинхронных шаблонов. JavaScript, как язык программирования, имеет две основные характеристики, обе важны для понимания того, как […]

18
Ноя
2019

Раскрываем тайну JavaScript sort()

От автора: в JavaScript есть метод sort(), который вы можете использовать в массивах. Но результаты почти всегда странные и не дают того, что вы изначально ожидали. Так, например, если у вас есть следующий массив [9, 8, 12, 1, 33, 21], sort() вернет [1, 12, 21, 33, 8, 9]. На первый взгляд, это не имеет смысла, […]

12
Ноя
2019

21 ноября, Москва: митап MSK VUE.JS #5

Пятая встреча энтузиастов, где будут обсуждать прогрессивный фреймворк Vue.js в приятной компании вместе с ведущими разработчиками и руководителями.
— Читать дальше «Митап MSK VUE.JS #5»

12
Ноя
2019

Советы по оптимизации JavaScript и улучшению загрузки сайта

От автора: в современном цифровом мире важно оставаться конкурентоспособным. Одним из параметров сохранения конкурентоспособности веб-сайтов является время загрузки. Если ваш сайт работает медленно, вы наверняка потеряете трафик, у вас будет более высокий показатель отказов и меньший оборот. Это означает, что с точки зрения бизнеса одним из наиболее важных аспектов, которые вам необходимо учитывать с самого […]

07
Ноя
2019

await верхнего уровня

От автора: await верхнего уровня позволяет разработчикам использовать ключевое слово await вне асинхронных функций. Оно действует как большая асинхронная функция, заставляя другие модули import ожидать ее, прежде чем они начнут оценивать тело. Старое поведение Когда async/ await был впервые введен, попытка использования await вне функции async приводила к SyntaxError. Многие разработчики использовали сразу вызываемые выражения […]

06
Ноя
2019

Как создать эффект расширения пунктов меню при наведении мыши

От автора: вы когда-нибудь использовали в проекте плагин WordPress Slider Revolution? Если ответ «да», вы могли заметить мини-панель инструментов, которая появляется в правом углу страницы конфигурации плагина. Первоначально видны только иконки, что делает все это красивым и компактным. Затем каждый раз при наведении курсора происходит расширение текста под ним. В этом руководстве давайте почерпнем вдохновение […]

06
Ноя
2019

Создание макета панели администрирования с помощью CSS и JavaScript

От автора: в этом руководстве мы создадим адаптивный макет панели администрирования с помощью CSS и немного JavaScript. Чтобы создать его, мы позаимствуем некоторые идеи из панели управления WordPress, например, ее боковое меню. В процессе создания мы столкнемся со множеством проблем, но они дадут нам хорошую практику для повышения навыков. Что мы будем создавать Без дальнейших […]

05
Ноя
2019

7 на первый взгляд простых вопросов на собеседовании по JavaScript

От автора: самые стрессовые для меня вещи в разработке программного обеспечения это: собеседование по кодированию и дотошный менеджер или товарищ по команде. Не JavaScript, не this, не CSS, не Internet Explorer, а именно эти две вещи. Если вы претендуете на должность старшего разработчика, который использует JavaScript, есть высокий шанс того, что вам зададут во время […]

03
Ноя
2019

Composition API во Vue 3 — плюсы, минусы и опыт использования

В Vue 3 на смену Options API приходит Composition API. Что это, где его применять, как он может упростить разработку, рассказывает Тихон Соколов
— Читать дальше «Composition API во Vue 3 — плюсы, минусы и опыт использования»

01
Ноя
2019

Создание JavaScript приложения для распознавания лиц, как в кино

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

01
Ноя
2019

Как обнаружить блокировщик рекламы

От автора: одно из неписанных правил Интернета заключается в том, что большая часть контента является «бесплатной»… за счет того, что веб-страница содержит рекламу и трекеры. В первые дни интернета это не было большой проблемой, но трекеры и рекламные объявления стали настолько навязчивыми и агрессивными, что вам почти обязательно нужно использовать расширение для браузера, блокирующее рекламу. […]

25
Окт
2019

Вышел Node.js 13.0 с обновлённым движком V8 и улучшенной поддержкой Python 3

Ещё разработчики добавили полную поддержку Unicode и стабилизировали API Workers Threads для создания многопоточных циклов обработки событий.
— Читать дальше «Вышел Node.js 13.0 с обновлённым движком V8 и улучшенной поддержкой Python 3»