React Native-在不影响性能/渲染的情况下处理大量JS代码的最佳方法



我正在研究react native中的一些特定用例,我希望在不干扰运行react nativeUI和动画的主线程的情况下执行一些繁重的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-阅读文档后,可以按照文档中提到的那样实现它-在InteractionManager.runAfterInteractions((处理程序中包装for循环。然而,这并不能完全解决问题。它下面还有另一个方法,名为setDeadline,它的文档很少。我认为它对处理大块数据很有用,而不是一次处理整个代码。不知道如何使用。

  2. RequestAnimationFrame/SetTimeout-未按预期工作

  3. React原生线程/工作者-像API这样的Web工作者在后台处理任务。这可以正常工作,还有一个额外的优势,即我们可以向工作线程发送/侦听消息,以启动/停止任务执行。根据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注入到web视图中可以吗?不确定。

我的问题是-

  1. 我想了解更多关于RN交互管理器的信息,尤其是setDeadline((方法-如何使用它以及它的作用
  2. 在这种用例中,哪种方法更好

我没有一个确切的答案,因为我对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。很有趣。我个人很想看到一些代码。我在这方面没有经验,但这听起来很令人兴奋。我认为webview肯定有助于将工作卸载到一个单独的线程,但我以前从未在这种情况下使用过它。

相关内容

  • 没有找到相关文章

最新更新