React Native - лучший подход для обработки тяжелого JS-кода без снижения производительности и рендеринга - PullRequest
0 голосов
/ 16 декабря 2018

Я искал какой-то конкретный вариант использования в реактивном нативе, где я хотел бы выполнить некоторые тяжелые операции JS, не нарушая основной поток, который запускает пользовательский интерфейс и анимации в реактивном нативе.

Примером может служить запускцикл for 10K раз, как только компонент приложения монтируется или любая анимационная последовательность запускается пользователем (например, переход к новой анимации просмотра, открытие анимации страницы с некоторыми подробностями и т. д.).

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

// animate the item details page (from item list page)
onItemPressed() {
// Some JS code to mimic heavy processing
console.log('starting...');
for (let i = 0; i < 5000; i++) {
  (Math.random() * 9999999) / 7;         
}
console.log('Finished');

// starting animation sequence
this.setState({animationPhase: 'phase-2'});
}

После прямого запуска кода выше анимация запаздывает из-за кода, который запускается до запуска анимации.

Я искал следующие подходы:

  1. Использование RN InteractionManager - После прочтения документации можно реализовать ее, как упомянуто в документации - обертывание цикла for внутри обработчика InteractionManager.runAfterInteractions ().Это, однако, не решает проблему полностью.Есть еще один метод под названием setDeadline , который плохо документирован.Я предполагаю, что это полезно для обработки фрагментов данных вместо обработки всего кода сразу.Не уверен, как его использовать.

  2. RequestAnimationFrame / SetTimeout - не работает должным образом

  3. Реагирует на собственные потоки / работники - веб-работники, такие как APIобрабатывать задачи в фоновом режиме.Это работает должным образом с дополнительным преимуществом, что мы можем отправлять / прослушивать сообщения в / из рабочего потока, чтобы запускать / останавливать выполнение задачи.Согласно документации RNThreads , мы можем использовать его как -

    import { Thread } from 'react-native-threads'; // import it in the required component
    
    this.thread = new Thread('./JS_FILE_THAT_HAS_HEAVY_DUTY_CODE.js'); // create new instance of it
    
    this.thread.onmessage = (message) => {} // listen to messages coming from the JS file
    
    this.thread.postMessage('Start'); // post message to the thread
    
    
    componentWillUnmount() {
        // stop the JS process
        this.thread.terminate();
     }
    
    // In thread.js file,
    
    import { self } from 'react-native-threads'; // import current worker context obj
    
    self.onmessage = message => {    // Listen to messages coming from parent script
    
       // start execution
    
    }
    
    self.postMessage('Completed');  // post messages to parent script
    
  4. Используя WebView - я еще не пробовал, но этот пост кажется полезным в этом случае, но нормально ли вставлять строковый javascript в веб-представление?Точно сказать не могу.

Мои вопросы -

  1. Я хотел бы узнать больше о RN Interaction Manager, особенно о методе setDeadline () - как его использовать и что этоделает.
  2. Какой подход лучше в таких случаях использования?

1 Ответ

0 голосов
/ 16 декабря 2018

У меня нет четкого ответа для вас, поскольку я также не очень хорошо знаком с InteractionManager.setDeadline(), но я думаю, что если вы посмотрите на тесты, вы поймете, что вам нужно.Часто тесты служат отличной заменой отсутствия документации.

Поэтому взгляните на InteractionManager-test.js, в частности, L230-L261

Там вы найдете эти тесты ...

it('should execute tasks in loop within deadline', () => {
    InteractionManager.setDeadline(100);
    BatchedBridge.getEventLoopRunningTime.mockReturnValue(10);
    const task1 = createSequenceTask(1);
    const task2 = createSequenceTask(2);
    InteractionManager.runAfterInteractions(task1);
    InteractionManager.runAfterInteractions(task2);

    jest.runOnlyPendingTimers();

    expectToBeCalledOnce(task1);
    expectToBeCalledOnce(task2);
  });

  it('should execute tasks one at a time if deadline exceeded', () => {
    InteractionManager.setDeadline(100);
    BatchedBridge.getEventLoopRunningTime.mockReturnValue(200);
    const task1 = createSequenceTask(1);
    const task2 = createSequenceTask(2);
    InteractionManager.runAfterInteractions(task1);
    InteractionManager.runAfterInteractions(task2);

    jest.runOnlyPendingTimers();

    expectToBeCalledOnce(task1);
    expect(task2).not.toBeCalled();

    jest.runOnlyPendingTimers(); // resolve1
    jest.runOnlyPendingTimers(); // task2

    expectToBeCalledOnce(task2);
});

Мне кажется, это способ разделить работу, которая может быть полезной.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...