Почему шаблон cancelledPromise считается лучше, чем «антишаблон» isMounted() в React?

См. здесь: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html А также здесь: Как отменить выборку на componentWillUnmount А здесь: смонтированный антипаттерн, отслеживание собственного свойства

В обоих случаях упоминаются 3 подхода:

  • В вашем promise.resolve проверьте this.IsMounted(), который React вернет вам правильно, если `Compounted Has Unmounted
  • В вашем promise.resolve проверьте _isMounted, который вы вручную отследили методом ComponentWillUnmount().
  • Используйте отменяемые обещания, чтобы ваш promise никогда не разрешил. И это решит все ваши проблемы и сделает его прекрасным.

За исключением третьего случая, ваш promise будет error(), но также может быть error() в других случаях (например, API не работает).

Так что на самом деле 3-й вариант сводится к: - В вашем promise.error проверьте errorPayload.IsCancelled, который вы вручную отследили в объекте cancellablePromise, который, в свою очередь, был запущен ручным вызовом в ComponentWillUnmount.

Итак, все три практически идентичны:

When you are handling your promise outcomes, check the value of this variable that is directly tied to whether the component has already unmounted.

Почему они утверждают, что 3-й вариант лучше остальных 2-х, а 1-й вариант — это антипаттерн.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
13
0
1 086
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Давайте представим, что действие, которое вызовет будущий вызов setState, выполняет много вычислений или выполняет множество сетевых запросов. Все эти ресурсы будут использованы, а затем когда-нибудь в будущем, когда промис разрешится, он поймет, что вся работа не нужна, так как пользователь уже покинул эту часть страницы, и вся работа будет отброшена. Это плохо для производительности и использования сети/памяти, особенно если у вас есть много элементов, которые появляются и исчезают. Если вы выберете вариант 3, только небольшое количество ресурсов будет потрачено впустую, пока не будет достигнута следующая точка остановки и ресурсы не будут освобождены. Я предполагаю, что они удалили 1) чтобы заставить кодировщиков использовать 3) и предложили 2) для случаев, когда миграция невозможна/сложна.

Неправда - отмена обещания НИЧЕГО не делает, пока обещание не будет разрешено - это не токены отмены, которые передаются серверу, выполняющему работу, - это просто флаги того, как обещание разрешается.

Brondahl 23.01.2019 13:37

@brondahl зависит от того, как вы отмените основные действия.

Jonas Wilms 24.01.2019 14:17

Интересно ... Однако я не сталкивался с этим раньше ... на основе этой страницы у вас все еще есть точно такая же логика обещаний, только теперь проверка if (err.name === 'AbortError'), а не if (err.isCancelled). (1/2)

Brondahl 25.01.2019 12:13

Что касается остановки работы, я был бы очень удивлен, если бы это ДЕЙСТВИТЕЛЬНО говорило серверу прекратить работу (т.е. убить поток сервера), если это реализуется на уровне браузера. (Поскольку для этого потребуется, чтобы каждый браузер знал, как отправить это сообщение на каждый сервер и серверную инфраструктуру). Я подозреваю, что это просто говорит браузеру не слушать ответ сервера. Таким образом, все, что вы делаете, — это продвигаете принцип «а потом ничего не делать» еще на один недорогой шаг вперед. (2/2)

Brondahl 25.01.2019 12:14

Компонентный метод isMounted устарел. Его больше нельзя использовать в React 16.

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

Это не проблема для отменяемых обещаний. Более того, этот шаблон позволяет фактически отменить асинхронный процесс, например. Axios фактически отменяет запрос XHR во время отмены. Тем не менее, чтобы это работало, требуется, чтобы вся цепочка обещаний знала об отмене. Это может быть утомительно, так как отмена не поддерживается в собственных промисах, включая async..await.

Наблюдаемые объекты предоставляют еще более мощные способы управления выполнением. Есть единственная точка (подписка), которая способна отменить всю цепочку, вызвав функцию отписки:

const unsubscribe = fetchData()
.mergeMap(asynchronousProcessing)
.mergeMap(yetAnotherAsynchronousProcessing)
.subscribe(data => this.setState(data));
Ответ принят как подходящий

Ключевым элементом здесь является то, что if (this.isMounted()) { setState(...) } является антипаттерном в целом. Это может привести к подавлению полезных предупреждений, поэтому к его появлению следует относиться с подозрением, поскольку в большинстве случаев оно представляет собой возможность скрыть реальные проблемы. Таким образом, даже в тех случаях, когда его поведение функционально такое же, как и у какого-либо другого подхода, этот другой подход предпочтительнее.

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

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

Я понимаю... мы говорим, что вызовы API в изоляции являются разумным использованием isMounted(). Но если мы используем отменяемые промисы, то это позволяет нам сказать: «Теперь isMounted() НИКОГДА не является правильным». Который тогда более удобен в сопровождении и лучше защищен для этих других случаев.

Brondahl 23.01.2019 16:53

Другая аналогия: GOTO (канонически) считаются вредными. Но if, while, break, continue и switch, по сути, просто делают одно и то же, но объявляют приемлемые ситуации, в которых разумно использовать эту концепцию.

Brondahl 19.02.2019 13:10

Другие вопросы по теме