Хобрук: Ваш путь к мастерству в программировании

Шаблон React и React Native для обработки ответов сервера

В прошлом я много занимался собственной мобильной разработкой как для Android (Java), так и для iOS (ObjC и Swift). Для моих приложений, подключенных к серверу, одной проблемой, которую мне пришлось решать должным образом, был обратный вызов, который вызывался после того, как приложение сделало HTTP-запрос. Например, предположим, что у меня есть экран (Activity в Android или ViewController в iOS), и внутри него я делаю HTTP-запрос к REST-серверу, ожидая в ответ какие-то данные. Большинство учебников (к сожалению) предоставляют примеры HTTP-ответа, вызывающего метод обратного вызова в самом Activity или ViewController. Да, на первый взгляд это кажется разумным, но в приложениях с несколькими Activity или ViewControllers возникает большая проблема — что произойдет, если пользователь уйдет с экрана после запроса, но до того, как вернется ответ? В этом случае приложение уничтожает память первой Activity или ViewController, поэтому, когда возвращается ответ, оно пытается вызвать метод для освобожденной памяти, что приводит к сбою.

Вместо этого нам пришлось использовать постоянный одноэлементный объект (например, класс, который расширяет приложение в Android или использовать делегат приложения в iOS) в качестве класса, реализующего функции обратного вызова. Любой экран, который хотел получить результаты, должен был зарегистрироваться для получения этих результатов (с помощью слушателей в Android или с помощью уведомлений в iOS). Если пользователь уйдет с экрана, соответствующие методы жизненного цикла экрана отменят регистрацию обработчика прослушивателя/уведомления на экране, чтобы никогда не было случая, когда метод обратного вызова вызывается для освобожденной памяти.

Теперь я начинаю использовать как React (в браузерах), так и React Native (в мобильных приложениях). Я использую модуль Axios для обработки HTTP-запросов. Опять же, все примеры, которые я вижу, показывают обратные вызовы в самом компоненте React, а не какой-либо шаблон, где есть какой-то постоянный синглтон или глобальный объект, который обрабатывает ответы и отправляет их на любые экраны, которые все еще активны на дисплее.

Итак, у меня есть несколько вопросов следующего содержания:

Для React (в браузере) это проблема? Могу ли я / должен ли я просто предоставить обратный вызов для самого компонента, и у браузера не будет проблем, если я уйду с экрана в середине запроса? Я подозреваю, что в наши дни код браузера довольно надежен, поэтому я сомневаюсь, что он приведет к сбою браузера, но вызовет ли это какие-либо проблемы с веб-приложением?

А как насчет React Native? Поскольку это в основном построено поверх нативного кода для мобильных устройств, столкнусь ли я с этой проблемой сбоя памяти, если я поставлю обратный вызов в сам компонент?

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

Обратите внимание, что я не буду использовать избыточность в своем коде — вместо этого я планирую использовать более простую структуру (hookstate, hookstate.js.org), которая позволит мне отслеживать глобальное состояние и использовать его внутри компонентов при обновлении. Это похоже на систему обратного вызова для глобального состояния, но мне не совсем понятен лучший шаблон для включения в него HTTP-запросов через такие модули, как Axios.

Предложения?


  • Я нашел некоторую информацию об AbortController, которая отвечает на некоторые из этих вопросов (см. freecodecamp.org/news/). Чего не хватает, так это того, как разрешить другому постоянному объекту (не смонтированному компоненту) получать результаты. Например, предположим, что я хочу отправить фоновую задачу на сервер и позже получить результаты. Я должен позволить пользователю уйти от экрана во время ожидания. 07.07.2020

Ответы:


1

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

import React, {useState, useEffect} from 'react'
import axios, {CancelToken} from 'axios'

const MyComponent = () => {
  const [blah, setBlah] = useState(null)

  useEffect(() => {
    //Axios comes with support for cancelling. See here
    //https://github.com/axios/axios#cancellation
    const source = CancelToken.source();
    let source = null

    axios.get('/some/url', {cancelToken: source.token})
      .then(({data}) => {
        //If the request is successful, we know the component wasn't unmounted.
        //Go ahead and call the state-modifying function.
        setBlah(data)
      })
      .catch((thown) => {
        //If something goes wrong, check to see if it is because of a cancel.
        //If it is, we probalby don't need to do anything.
        if (axios.isCancel(thrown)) {
          console.log("Cancelled")
        }
        else {
          //Otherwise, we can handle the error gracefully
        }
      })
    //If you return a function from setEffect, it will be
    //executed when the component is about to unmount (componentWillUnmount)
    //See https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1
    return () => source.cancel()
  }, []) //This will only run once (the first time the component renders)

  return <pre>{blah}</pre>
}

По сути, мы используем useEffect для запуска запроса через Axios. Затем мы используем встроенную функцию отмены Axios (https://github.com/axios/axios#cancellation ). Мы вызываем функцию отмены, когда компонент размонтирован. В результате предложение then запроса axios не будет выполняться. В данном конкретном случае это не имеет большого значения; мы используем внутреннее состояние компонента, поэтому после размонтирования не будет никакого эффекта от запуска setBlah. Однако, если, скажем, вы использовали Redux для глобального состояния или какой-либо другой шаблон редуктора, возможно, что ваше предложение then вызовет какое-то внешнее действие даже после размонтирования.

Итак, чтобы ответить на вопрос, имеет ли это значение? Ответ: это зависит. Если вы можете сохранить свое состояние локальным для компонента, который выдает запрос, возможно, нет. Если, как вы намекаете, вы планируете иметь какое-то глобальное состояние и раскрывать способы изменения этого состояния (Redux или контекст, который предоставляет редюсер), то это, безусловно, может. Подобный шаблон должен избегать вызова функции изменения состояния в случае размонтирования вашего компонента.

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

07.07.2020
Новые материалы

Не зря же это называют интеллектом
Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

LeetCode Проблема 41. Первый пропущенный положительный результат
LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

Расистский и сексистский робот, обученный в Интернете
Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

Управление состоянием в микрофронтендах
Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

Структуры данных в C ++ - Часть 1
Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

Как я опубликовал свое первое приложение в App Store в 13 лет
Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..