Почему асинхронная работа в ComponentDidMount приводит к визуальному отставанию при навигации, если не ожидается простой timeOut? - PullRequest
1 голос
/ 22 октября 2019

У меня есть нативное приложение с вкладками и у меня есть 2 связанных вопроса:

  1. Почему навигация между экранами визуально запаздывает при выполнении асинхронной работы (такой как отправка сетевого запроса) в целиметод просмотра componentDidMount? Официальная документация упоминает этот метод как подходящее место для обработки сетевых запросов, но даже когда componentDidMount и вызываемые им функции объявлены как async () => визуальная задержка при инициации навигации является явной. Эта визуальная задержка возникает в начале навигации, до того, как целевой компонент перемещается или фокусируется, и возникает даже тогда, когда асинхронная работа никак не изменяет состояние приложения, что может повлиять на отображение целевого компонента.

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

const timeOut = t => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`Completed in ${t}`);
    }, t);
  });
};

componentDidMount = async () => { // async or not, delay occurs
  await timeOut(0); //This line prevents navigation lag
  NetworkRequest.getData(payload);
}
...

static getData = payload => {
fetch("API_ENDPOINT", {
      method: "POST",
      body: payload
    })
      .then(response => response.json())
      .then(response => {
              //process response 
       })
}

Ожидается ли NetworkRequest.getData или нетзадержка навигации присутствует, не ожидая этого искусственного мини-обещания заранее. Мне кажется, что я неправильно понимаю, как реагируют нативные жизненные циклы или какая-то другая ключевая часть процесса рендеринга, потому что я не могу себе представить, почему это маленькое ожидание необходимо, чтобы «обмануть» метод, чтобы он стал визуально асинхронным ...

РЕДАКТИРОВАТЬ: Теперь, когда я знаю больше об очередях сообщений и очередях заданий, есть смысл, что потенциальный источник визуальной задержки может возникнуть из-за заклинивания очереди заданий с большой задачей. Ожидая timeOut в методе async, этот метод фактически становится объектом с самым низким приоритетом в очереди заданий. Кажется, что странные переходы экрана были бы неблокирующими, поскольку пользовательский интерфейс в это время был недоступен, но я уверен, что у реагирующих нативных разработчиков была причина ... Также кажется довольно странным, что документация рекомендует выполнять асинхронную работу в этом методе, когдаон будет блокироваться без этого перехода в очередь voodoo ... Есть ли лучший способ указать приоритет очереди сообщений / заданий в методе Javascript, кроме простого асинхронного? Или ожидает пустое время. Единственный способ указать обработку с наименьшим приоритетом.

Использование expo SDK 34, в котором используется собственная реакция реагирования 0,59

реакция-навигация 3,11

И Реакция 16,8.3

РЕДАКТИРОВАТЬ: Какое совпадение! Экспериментальная поддержка Suspense for Fetching только что была объявлена ​​Дэном 5 часов назад :) Подробнее здесь

Ответы [ 2 ]

1 голос
/ 23 октября 2019

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

Добавляя await timeOut(0), вы больше не делаете его синхронным. Теперь он вызывается в следующем цикле событий, что означает, что любые синхронные действия до того, как это уже закончится.

0 голосов
/ 22 октября 2019

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

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

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

Я не уверен, чтоNetworkRequest.getData делает, я могу что-то с этим поделать, но если он возвращает обещание, может быть, вам стоит попробовать использовать await.

Вы также забыли добавить async к своему componentDidMount.

async componentDidMount(){
  await NetworkRequest.getData(payload);
}
...