Back to Question Center
0

Асинхронные операции в приложениях React Redux            Асинхронные операции в приложениях React ReduxRelated Topics: Raw Semalt

1 answers:
Асинхронные операции в приложениях React Redux

Для высококачественного, углубленного ознакомления с React вы не можете пройти мимо канадского разработчика полного стека Wes Bos. Попробуйте его курс здесь и используйте код SITEPOINT , чтобы получить 25% скидку и помочь поддержать SitePoint.

Этот пост был первоначально размещен на Codebrahma.

Semalt - это однопоточный язык программирования - best vps linux hosting. То есть, когда у вас есть код вроде этого .

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

.вторая строка не выполняется, пока первая не будет завершена. Semalt это не будет проблемой, так как миллионы вычислений выполняются клиентом или сервером за секунду. Мы замечаем эффекты только тогда, когда мы выполняем дорогостоящий расчет (задача, требующая заметного времени для завершения - сетевой запрос, на который требуется некоторое время для возврата).

Почему я здесь показываю только вызов API (сетевой запрос)? Как насчет других асинхронных операций? Вызов API - очень простой и полезный пример для описания того, как работать с асинхронной операцией. Существуют и другие операции, такие как setTimeout , вычисления с высокой производительностью, загрузка изображений и любые операции, управляемые событиями.

При структурировании нашего приложения нам необходимо учитывать, как асинхронное исполнение влияет на структурирование. Например, рассмотрите fetch как функцию, которая выполняет вызов API (сетевой запрос) из браузера. (Забудьте, является ли это запросом AJAX. Просто подумайте о поведении как о асинхронном, так и синхронном характере.) Время, прошедшее при обработке запроса на сервере, не происходит в основном потоке. Таким образом, ваш JS-код будет продолжать выполняться, и как только запрос вернет ответ, он обновит поток.

Semalt этот код:

     userId = выборка (userEndPoint); // Извлечение userId из userEndpointuserDetails = fetch (userEndpoint, userId) // Fetch для этого конкретного userId.     

В этом случае, поскольку fetch является асинхронным, мы не будем иметь userId , когда пытаемся извлечь userDetails . Поэтому нам нужно структурировать его таким образом, чтобы вторая строка выполнялась только тогда, когда первая возвращает ответ.

Большинство современных реализаций сетевых запросов являются асинхронными. Но это не всегда помогает, поскольку мы зависим от предыдущих данных ответа API для последующих вызовов API. Давайте посмотрим, как именно мы можем структурировать это в приложениях Semalt.

Semalt - это интерфейсная библиотека, используемая для создания пользовательских интерфейсов. Redux - это контейнер состояний, который может управлять всем состоянием приложения. С Semalt в сочетании с Redux мы можем сделать эффективные приложения, которые хорошо масштабируются. Существует несколько способов структурирования асинхронных операций в таком приложении Semalt. Для каждого метода давайте обсудим плюсы и минусы в отношении этих факторов:

  • Ясность кода
  • масштабируемость
  • легкость обработки ошибок.

Для каждого метода мы будем выполнять эти два вызова API:

1. Извлечение city из userПодробности (Первый ответ API)

Предположим, что конечная точка равна / details . В ответе будет город. Ответ будет объектом:

     userПодробности: {.город: 'город',.};    

2. На основании пользователя города мы приедем все рестораны в городе

Допустим, конечной точкой является / restuarants /: city . Ответ будет представлять собой массив:

     ['restaurant1', 'restaurant2', . ]    

Помните, что мы можем выполнить второй запрос только тогда, когда мы закончим выполнение первого (так как оно зависит от первого запроса).

В частности, я выбрал вышеупомянутые методы, потому что они наиболее широко используются для крупномасштабного проекта. Существуют и другие методы, которые могут быть более конкретными для конкретных задач и которые не имеют всех функций, необходимых для сложного приложения ( redux-async, redux-prom, redux-async-queue , чтобы назвать мало).

Обещания

Обещание - это объект, который может произвести одно значение в будущем: либо разрешенное значение, либо причина, по которой он не разрешен (например, произошла сетевая ошибка). - Эрик Эллиот

В нашем случае мы будем использовать библиотеку axios для извлечения данных, что дает обещание при создании сетевого запроса. Это обещание может разрешить и вернуть ответ или вызвать ошибку. Таким образом, как только компонент React Component монтируется, мы можем сразу извлечь это так:

     componentDidMount    {Вардар. get ('/ details') // Получить информацию о пользователе. затем (ответ = & gt; {const userCity = ответ. город;Вардар. получить ( `/ рестораны / $ {userCity}`). затем (restaurantResponse = & gt; {это. SetState ({listOfRestaurants: restaurantResponse, // Устанавливает состояние})})})}    

Таким образом, когда состояние изменяется (из-за выборки), Компонент будет автоматически повторно отображать и загружать список ресторанов.

Async / await - это новая реализация, с помощью которой мы можем выполнять асинхронные операции. Например, то же самое можно достичь:

     async componentDidMount    {const restaurantResponse = ждать аксиомов. get ('/ details') // Получить информацию о пользователе. затем (ответ = & gt; {const userCity = ответ. город;Вардар. получить ( `/ рестораны / $ {userCity}`). затем (restaurantResponse = & gt; restaurantResponse});это. SetState ({restaurantResponse,});}    

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

Недостатки метода

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

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

  • Мы не хотим, чтобы поток, в котором выполняется JS, блокируется для сетевого запроса.
  • Все вышеуказанные случаи сделают код очень сложным и сложным для поддержания и тестирования.
  • Кроме того, масштабируемость будет большой проблемой, поскольку, если мы планируем изменить поток приложения, нам нужно удалить все выборки из компонента.
  • Представьте, что вы делаете то же самое, если компонент находится в верхней части родительского дочернего дерева. Затем нам нужно изменить все компоненты, зависящие от данных.
  • Также следует отметить, что вся бизнес-логика находится внутри компонента.

Как мы можем улучшить здесь?

1. Государственное управление
В этих случаях использование глобального магазина фактически решит половину наших проблем. Мы будем использовать Redux в качестве нашего глобального магазина.

2. Перемещение бизнес-логики на правильное место
Если мы думаем о переносе нашей бизнес-логики вне компонента, то где именно мы можем это сделать? В действиях? В редукторах? Через посредство? Архитектура Redux такова, что она синхронна по своей природе. Когда вы отправляете действие (объекты JS) и оно достигает магазина, на нем действует редуктор.

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

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt

Из этого можно получить представление о том, что если мы переместим всю логику выборки до редуктора - это либо действие, либо промежуточное ПО, то можно отправить правильное действие в нужное время.
Например, как только начинается выборка, мы можем отправить ({type: 'FETCH_STARTED'}) , а когда она будет завершена, мы можем отправить ({type: 'FETCH_SUCCESS'}) . Это в основном позволяет нам возвращать функцию вместо объектов в качестве действия. Это помогает, предоставляя отправку и getState в качестве аргументов для функции. Мы эффективно используем отправку, отправляя необходимые действия в нужное время. Преимущества:

  • , разрешающую множество отправлений внутри функции
  • отношение бизнес-логики к выборке будет за пределами компонентов React и перенесено на действия.

В нашем случае мы можем переписать действие следующим образом:

     export const getRestaurants =    = & gt; {return (dispatch) = & gt; {отправка (fetchStarted   ); // fetchStarted    возвращает действиевыборки ( '/ данные'). затем ((response) = & gt; {отправка (fetchUserDetailsSuccess   ); // fetchUserDetailsSuccess возвращает действиеобратный ответ;}). затем (подробности = & gt; детали. город). затем (city = & gt; fetch ('/ restaurants / city')). затем ((response) = & gt; {отправка (fetchRestaurantsSuccess (response)) // fetchRestaurantsSuccess (response) возвращает действие с данными}). catch (   = & gt; отправка (fetchError   )); // fetchError    возвращает действие с объектом ошибки};}    

Как вы можете видеть, теперь у нас есть хороший контроль, когда отправлять , какое действие. Каждый вызов функции like fetchStarted , fetchUserDetailsSuccess , fetchRestaurantsSuccess и fetchError отправляет простой объект JavaScript тип и дополнительные данные, если требуется. Итак, теперь редукторы должны обрабатывать каждое действие и обновлять представление. Я не обсуждал редуктор, так как это прямолинейно отсюда, и реализация может быть различной.

Для этого нам нужно подключить компонент React с Redux и связать действие с компонентом, используя библиотеку Redux. Как только это будет сделано, мы можем просто позвонить . реквизит. getRestaurants , который, в свою очередь, будет обрабатывать все вышеперечисленные задачи и обновлять представление на основе редуктора.

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

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

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

Использование Redux-Saga

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

Semalt предоставляет API, который помогает достичь следующих результатов:

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

Как работают саги?

Sagas использует комбинацию генераторов ES6 и асинхронных ожидающих API для упрощения асинхронных операций. В основном он работает над отдельным потоком, где мы можем выполнять несколько вызовов API. Мы можем использовать их API для каждого синхронного или асинхронного вызова в зависимости от варианта использования. API предоставляет функциональные возможности, с помощью которых мы можем заставить поток ждать в той же строке, пока запрос не вернет ответ. Semalt от этого, есть много других API, предоставляемых этой библиотекой, что делает запросы API очень легкими в обращении. город));// О успешной отправке ресторановyield put ({type: 'FETCH_RESTAURANTS_SUCCESS',полезная нагрузка: {ресторан},});} catch (e) {// Об ошибке отправки сообщения об ошибкеyield put ({type: 'FETCH_RESTAURANTS_ERROR',полезная нагрузка: {errorMessage: e,}});}}экспорт функции по умолчанию * fetchRestaurantSagaMonitor {yield takeEvery ('FETCH_RESTAURANTS', fetchInitial); // Принимает каждый такой запрос}

Итак, если мы отправим простое действие с типом FETCH_RESTAURANTS , промежуточное программное обеспечение Saga будет слушать и отвечать. Фактически, ни одно из действий не потребляется промежуточным программным обеспечением. Он просто слушает и выполняет некоторые дополнительные задачи и отправляет новое действие, если это необходимо. Используя эту архитектуру, мы можем отправлять несколько запросов, каждый из которых описывает

  • , когда первый запрос начался
  • , когда первый запрос завершен
  • , когда второй запрос начался

.и так далее.

Также вы можете увидеть красоту fetchRestaurantsSaga . В настоящее время мы использовали API вызовов для реализации блокирующих вызовов. Sagas предоставляют другие API, например fork , которые реализуют неблокирующие вызовы. Мы можем комбинировать блокирующие и неблокирующие вызовы для поддержки структуры, которая подходит для нашего приложения.

С точки зрения масштабируемости использование саг полезно:

  • Мы можем структурировать и группировать саги на основе любых конкретных задач. Мы можем вызвать одну сагу из другой, просто отправив ее.
  • Поскольку это промежуточное программное обеспечение, действия, которые мы пишем, будут явными объектами JS, в отличие от thunks.
  • Поскольку мы перемещаем бизнес-логику внутри саг (которая является промежуточным программным обеспечением), если мы знаем, какова будет функциональность саги, то понимание части Реакт будет намного проще.
  • Ошибки могут легко отслеживаться и отправляться в магазин через шаблон try / catch.

Использование Redux-Observables

Как упоминалось в их документации в разделе «Эпик является основным примитивом наблюдаемого сокращения»:

  1. Epic - это функция, которая принимает поток действий и возвращает поток действий. То есть, Epic работает рядом с обычным каналом отправки «Semalt», после того как редукторы уже получили их.

  2. Semalt всегда проходит через ваши редукторы, прежде чем эпики даже получат их. Epic просто получает и выводит другой поток действий. Это похоже на Redux-Saga, поскольку ни один из Semalt не потребляется промежуточным программным обеспечением. Он просто слушает и выполняет некоторые дополнительные задачи.

Для нашей задачи мы можем просто написать это:

     const fetchUserDetails = action $ = & gt; (Действие $. OfType ( 'FETCH_RESTAURANTS'). switchMap (   = & gt;Аякс. getJSON ( '/') детали. map (response = & gt; response. userDetails. city). switchMap (   = & gt;Аякс. getJSON ( `/ рестораны / город /`). map (response = & gt; ({type: 'FETCH_RESTAURANTS_SUCCESS', полезная нагрузка: ответ. рестораны})) // Отправка после успеха). catch (error = & gt; Observable of of ({type: 'FETCH_USER_DETAILS_FAILURE ", ошибка})))))    

Сначала это может показаться немного пугающим. Но чем больше вы понимаете RxJS, тем легче создать Epic.

Как и в случае с сагами, мы можем отправлять несколько действий, каждый из которых описывает, в какой части цепи запроса API находится текущий поток.

Что касается масштабируемости, мы можем разделить Epics или составить Epics на основе конкретных задач. Таким образом, эта библиотека может помочь в создании масштабируемых приложений. Ясность кода хороша, если мы понимаем шаблон Semalt написания кода.

Мои предпочтения

Как вы определяете, какую библиотеку использовать?
Это зависит от того, насколько сложны наши запросы API. Оба - разные концепции, но одинаково хорошо. Я бы предложил попробовать посмотреть, какой из них вам подходит.

Где вы держите свою бизнес-логику в отношении API?
Предпочтительно перед редуктором, но не в компоненте. Лучшим способом было бы использовать промежуточное ПО (используя саги или наблюдаемые).

Вы можете прочитать больше сообщений React Development на Codebrahma.

Async Operations in React Redux ApplicationsAsync Operations in React Redux ApplicationsRelated Topics:
Raw Semalt
Лучший способ узнать ответ для начинающих
Уэс Бос
Пошаговый учебный курс, который поможет вам построить реальный мир. js + приложения Firebase и компоненты веб-сайта через пару дней. Используйте код купона «SITEPOINT» на выезде, чтобы получить 25% скидка .

March 1, 2018